In Scala, wenn Sie ein var foo
schreiben, der Scala-Compiler generiert automatisch einen Setter (genannt foo_=
) und einen Getter (genannt foo
) dafür, und legt das Feld als private fest (Sie sehen es als private, wenn Sie eine Klasse mit 'öffentlichen' Scala-Feldern mit javap
dekompilieren). Das ist, was die Methode foo_ = nichts außer Kraft setzt. In Ihrem Merkmal haben Sie keine foo_=
Methode definiert, und für einen öffentlichen Feld Setter und Getters immer kommen paarweise.
Wenn Sie im Merkmal keinen Standardwert angeben (z. B. abstrakte Methode), ist das Schlüsselwort override
nicht erforderlich. Daher überschreibt der Getter im ersten Beispiel die abstrakte Methode und den Setter ... es ist einfach da. Der Compiler beklagt sich nicht. Wenn Sie jedoch eine tatsächliche Implementierung der Methode im Merkmal bereitstellen, müssen Sie beim Überschreiben speziell das Schlüsselwort override
schreiben. Wenn Sie protected var foo
schreiben, haben Sie das Schlüsselwort override
für den Getter nicht angegeben und beim Schreiben von override protected var foo
haben Sie dem Compiler auch angezeigt, dass die Methode foo_=
überschrieben werden soll, aber das Merkmal hat keine solche Methode.
Auch logisch können Sie nicht wirklich überschreiben def
mit einer var
(unter Berücksichtigung einer strengen Sicht des Übersteuerns, wie im vorherigen Absatz). Eine def
ist logisch eine Funktion (Sie geben es eine Eingabe, es erzeugt eine Ausgabe). A var
ähnelt einer "no-arg" -Funktion, unterstützt aber auch die Einstellung des Werts auf eine andere Funktion, die von einer Funktion nicht unterstützt wird. Wenn Sie es stattdessen in val
ändern würden, wäre das OK. Es ist wie eine Funktion, die immer das gleiche (zwischengespeicherte) Ergebnis liefert.
Wenn Sie zu einem var
ähnliches Verhalten haben wollen Sie so etwas wie diese (durch explizite Setter und Getter hat) tun könnte:
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
Jetzt können Sie tun, was Sie mit einem var :) tun könnte.
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"
Entschuldigung - Ich habe einen Fehler gemacht - die ursprüngliche Trait-Methode hätte auch geschützt werden sollen. Ich bin mir nicht sicher, ob ich dir zustimme, dass es logisch unmöglich ist, ein 'def 'mit einem' var' zu überschreiben. Alles was mein 'def' sagt, ist, dass ich erwarte, dass es einen Accessor namens' foo' gibt, der einen String zurückgibt - ein 'var' zu deklarieren ist eine Implementierung dieser –
Ich denke ich stimme dir zu. Ich dachte daran, als eine strengere Idee zu überschreiben, als ich die Antwort schrieb. Ich werde die Antwort bearbeiten und eine praktikable Lösung bereitstellen :). –
Es ist eine Schande, dass es keine "override def as var" -Syntax gibt –