In Scala, quando si scrive un var foo
, il compilatore Scala genera automaticamente un setter (chiamato foo_=
) e un getter (chiamato foo
) per esso e imposta il campo come privato (lo vedrete come privato se decompilate una classe con campi Scala "pubblici" con javap
). Questo è ciò che significa il metodo 'method foo_ = overrides nothing'. Nel tuo tratto non hai definito un metodo foo_=
, e per un field setter e getter pubblici sempre venire in coppia.
Se non si fornisce un valore predefinito nel tratto (cioè astratto metodo), quindi la parola chiave override
non è necessario. Pertanto, nel tuo primo esempio, il getter sovrascrive il metodo astratto e il setter ... è proprio lì. Il compilatore non si lamenta. Tuttavia, quando fornisci un'implementazione effettiva del metodo nel tratto, devi scrivere specificamente la parola chiave override
quando esegui l'override. Quando si scrive protected var foo
, non è stata specificata la parola chiave per il getter e quando si scrive override protected var foo
, è stato anche indicato al compilatore che il metodo foo_=
deve essere sovrascritto, ma il tratto non ha tale metodo.
Inoltre, logicamente non è possibile sovrascrivere uno def
con un var
(considerando una visione rigorosa dell'override, come nel paragrafo precedente). A def
è logicamente una funzione (gli dai un input, produce un output). Un var
è simile a una funzione no-arg, ma supporta anche l'impostazione del suo valore su qualcos'altro, un'operazione che non è supportata da una funzione. Invece, se dovessi cambiarlo in uno val
, sarebbe OK. È come una funzione che produce sempre lo stesso risultato (memorizzato nella cache).
Se si vuole avere un comportamento simile ad un var
si potrebbe fare qualcosa di simile (avendo setter esplicito e getter):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Ora si può fare qualsiasi cosa si potrebbe fare con un var :).
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"
fonte
2009-09-08 11:08:13
Mi dispiace - ho fatto un errore - il metodo del tratto originale avrebbe dovuto essere protetto anche. Non sono sicuro di essere d'accordo con te sul fatto che non sia logicamente possibile sovrascrivere un 'def' con un' var'. Tutto il mio 'def' sta dicendo è che mi aspetto che ci sia un accessore chiamato' foo' che restituisce una stringa - dichiarando che 'var' è un'implementazione di questo –
Penso di essere d'accordo con te. Stavo pensando di scavalcare come una nozione più severa quando ho scritto la risposta. Modificherò la risposta e fornirò una soluzione praticabile :). –
È un peccato che non ci sia una sintassi di 'override def as var' –