class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
Diese Codezeilen werden ausgegeben 12
, obwohl sie person.age=20
erfolgreich ausgeführt wurden. Ich habe festgestellt, dass dies passiert, weil ich def in verwendet habe def person = new Person("Kumar",12)
. Wenn ich var oder val benutze, ist die Ausgabe 20
. Ich verstehe, die Standardeinstellung ist val in scala. Dies:
def age = 30
age = 45
... gibt einen Kompilierungsfehler aus, da es sich standardmäßig um einen Wert handelt. Warum funktionieren die ersten Zeilen oben nicht richtig und machen auch keine Fehler?
val
geändert werden, das Objekt, auf das sich ein Wert bezieht, jedoch nicht. Aval
ist keine Konstante.List
als markierenfinal
, aber seinen Inhalt ändern.Ich würde mit der Unterscheidung beginnen, die in Scala zwischen def , val und var besteht .
def - definiert eine unveränderliche Bezeichnung für den Inhalt der rechten Seite, die träge ausgewertet wird - nach Namen auswerten.
val - definiert ein unveränderliches Label für den Inhalt der rechten Seite, das eifrig / sofort bewertet wird - bewertet nach Wert.
var - definiert eine veränderbare Variable , die anfänglich auf den ausgewerteten Inhalt der rechten Seite gesetzt wird.
Beispiel def
Beispiel, val
Beispiel var
Gemäß den obigen Angaben können Beschriftungen von def und val nicht neu zugewiesen werden, und im Falle eines Versuchs wird ein Fehler wie der folgende ausgelöst:
Wenn die Klasse wie folgt definiert ist:
und dann instanziiert mit:
Für diese bestimmte Instanz von Person (dh 'personA') wird eine unveränderliche Bezeichnung erstellt. Immer wenn das veränderbare Feld "Alter" geändert werden muss, schlägt ein solcher Versuch fehl:
Wie erwartet ist 'Alter' Teil eines nicht veränderlichen Labels. Die richtige Vorgehensweise besteht darin, eine veränderbare Variable zu verwenden, wie im folgenden Beispiel:
wie aus der Referenz der veränderlichen Variablen hervorgeht (dh 'personB') geht hervor, dass das klassenveränderliche Feld 'age' geändert werden kann.
Ich möchte immer noch betonen, dass alles von dem oben genannten Unterschied herrührt, der für jeden Scala-Programmierer klar sein muss.
quelle
personA
et al. scheint aus. Ob das Ändern desage
Mitglieds funktioniert oder nicht, hängt davon ab, ob Siedef personA
oder verwendenvar personB
. Der Unterschied besteht darin, dass Sie in demdef personA
Fall diePerson
von Ihrer ersten Auswertung von zurückgegebene -instance ändernpersonA
. Diese Instanz wird geändert, aber es ist nicht das, was zurückgegeben wird , wenn Sie noch einmal auszuwertenpersonA
. Stattdessen tunpersonA.age
Sie dies beim zweiten Mal effektivnew Person("Tim",25).age
.Mit
Sie definieren eine Funktion / Lazy-Variable, die immer eine neue Personeninstanz mit dem Namen "Kumar" und dem 12. Lebensjahr zurückgibt. Dies ist völlig gültig und der Compiler hat keinen Grund, sich zu beschweren. Wenn Sie person.age aufrufen, wird das Alter dieser neu erstellten Personeninstanz zurückgegeben, das immer 12 Jahre beträgt.
Beim Schreiben
Sie weisen der Eigenschaft age in der Klasse Person einen neuen Wert zu, der gültig ist, da age als deklariert ist
var
. Der Compiler wird sich beschweren, wenn Sie versuchen,person
ein neues Personenobjekt wie neu zuzuweisenquelle
Um eine andere Perspektive zu bieten, bedeutet "def" in Scala etwas, das jedes Mal ausgewertet wird, wenn es verwendet wird, während val etwas ist, das sofort und nur einmal ausgewertet wird . Hier bedeutet der Ausdruck
def person = new Person("Kumar",12)
, dass wir immer dann einennew Person("Kumar",12)
Anruf erhalten , wenn wir "Person" verwenden . Daher ist es natürlich, dass die beiden "person.age" nicht miteinander verwandt sind.So verstehe ich Scala (wahrscheinlich "funktionaler"). Ich bin mir nicht sicher ob
ist wirklich das, was Scala damit meinen will. Ich denke zumindest nicht so gerne ...
quelle
Wie Kintaro bereits sagt, ist person eine Methode (wegen def) und gibt immer eine neue Person-Instanz zurück. Wie Sie herausgefunden haben, würde es funktionieren, wenn Sie die Methode in var oder val ändern:
Eine andere Möglichkeit wäre:
In
person.age=20
Ihrem Code ist jedoch zulässig, wenn Sie einePerson
Instanz von derperson
Methode zurückerhalten , und in dieser Instanz dürfen Sie den Wert von a ändernvar
. Das Problem ist, dass Sie nach dieser Zeile keinen Verweis mehr auf diese Instanz haben (da jeder Aufruf vonperson
eine neue Instanz erzeugt).Dies ist nichts Besonderes, Sie würden in Java genau das gleiche Verhalten haben:
quelle
Nehmen wir Folgendes:
und schreiben Sie es mit gleichwertigem Code neu
Siehe,
def
ist eine Methode. Es wird jedes Mal ausgeführt, wenn es aufgerufen wird, und jedes Mal, wenn es zurückkehrt (a)new Person("Kumar", 12)
. Und dies ist kein Fehler in der "Zuweisung", da es sich nicht wirklich um eine Zuweisung handelt, sondern nur um einen Aufruf derage_=
Methode (bereitgestellt vonvar
).quelle