Scala-Klasse-Mitglieder und Konstruktor-Parameter name clash
Betrachten Sie die folgende Klasse in Java geschrieben:
class NonNegativeDouble {
private final double value;
public NonNegativeDouble(double value) {
this.value = Math.abs(value);
}
public double getValue() { return value; }
}
Es wird ein final-Feld namens value
ist, dass die Initialisierung im Konstruktor, indem Sie den parameter namens gleich und anwenden einer Funktion auf es.
Möchte ich etwas schreiben, so ähnlich wie es in Scala. Auf den ersten, habe ich versucht:
class NonNegativeDouble(value: Double) {
def value = Math.abs(value)
}
Aber der compiler meckert: Fehler: überladene Methode Wert muss der Ergebnistyp
Offensichtlich ist der compiler denkt, dass der Ausdruck value
im inneren der Ausdruck Math.abs(value)
bezieht sich auf die Methode definiert wird. Also, die Methode definiert ist rekursiv, also muss ich die zurück geben. Also, der code, den ich schrieb, der nicht tut, was ich erwartet hatte, es zu tun: ich wollte value
innen Math.abs(value)
beziehen sich auf die Konstruktor-parameter value
, und nicht auf die Methode definiert wird. Es ist, als ob der compiler implizit Hinzugefügt this.
zu Math.abs(this.value)
.
Hinzufügen val
oder var
(oder private ...
Varianten), um die parameter des Konstruktors nicht scheinen zu helfen.
So, meine Frage ist: kann ich definieren, eine Eigenschaft mit dem gleichen Namen wie ein parameter des Konstruktors, aber vielleicht einen anderen Wert? Wenn ja, wie? Wenn nicht, warum?
Dank!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nein, das können Sie nicht. In Scala, Konstruktor-Parameter sind Eigenschaften, so dass es keinen Sinn macht, neu zu definieren, Sie.
Die Lösung, natürlich, ist die Verwendung anderer name:
So wie hier verwendet,
initValue
wird nicht Teil der erzeugten Instanzen. Jedoch, wenn Sie es in einemdef
oder einem Muster übereinstimmende Erklärung ab, dann wird es ein Teil von jeder Instanz der Klasse.@Daniel C. Sobral
dein code ist richtig, aber "Konstruktor-Parameter-Eigenschaften",das ist nicht wahr.
Ein Beitrag von der offiziellen Website, sagte,
Und Martin ' s Antwort bestätigt die Wahrheit:
Also normalerweise können wir noch behandeln primären Konstruktor-Parameter wie normale parameter der Methode, aber wenn die Parameter verwiesen wird, die von jeder der Methoden, der compiler clever schalten Sie es in einen privaten Bereich.
Wenn jeder formale parameter vorangestellt val, erzeugt der compiler eine getter-definition automatisch.wenn var erzeugt eine setter-zusätzlich. finden Sie die Sprache, die Spezifikation in Abschnitt 5.3.
Die alles über die primären Konstruktor-Parameter.
Können Sie prüfen, parametrische Feld
Es ist definiert Felder und Parameter mit dem gleichen Namen "Wert", "name".
Sie können hinzufügen Modifikatoren wie private ...
NonNegativeDouble
, deren .Wert würde eigentlich zurückgeben negative Doppel.Im Fall von
case classes
es sein sollte:Die Umsetzung der
copy
ist erforderlich, um zu verhindern, dass die sintesized version des Compilers, die Bindung derinitValue
argument.Ich erwarte, dass der compiler ist intelligent genug, um nicht behalten die «extra-Platz» für die
initValue
. Ich habe nicht überprüft, dieses Verhalten.