class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
Ces lignes de code sortent 12
, même si elles ont person.age=20
été exécutées avec succès. J'ai trouvé que cela se produit parce que j'ai utilisé def in def person = new Person("Kumar",12)
. Si j'utilise var ou val, la sortie est 20
. Je comprends que la valeur par défaut est val dans scala. Ce:
def age = 30
age = 45
... donne une erreur de compilation car c'est un val par défaut. Pourquoi le premier ensemble de lignes ci-dessus ne fonctionne-t-il pas correctement et ne fait-il pas d'erreur?
val
peut être changé mais l'objet auquel se réfère un val ne le peut pas. Aval
n'est pas une constante.List
commefinal
, mais vous pouvez modifier son contenu.Je commencerais par la distinction qui existe dans Scala entre def , val et var .
def - définit une étiquette immuable pour le contenu du côté droit qui est évalué paresseusement - évalué par nom.
val - définit une étiquette immuable pour le contenu de droite qui est évalué avec empressement / immédiatement - évalué par valeur.
var - définit une variable mutable , initialement définie sur le contenu du côté droit évalué.
Exemple, def
Exemple, val
Exemple, var
Selon ci-dessus, les étiquettes de def et val ne peuvent pas être réaffectées, et en cas de tentative, une erreur comme celle ci-dessous sera déclenchée:
Lorsque la classe est définie comme:
puis instancié avec:
une étiquette immuable est créée pour cette instance spécifique de Person (c'est-à-dire «personA»). Chaque fois que le champ mutable 'age' doit être modifié, une telle tentative échoue:
comme prévu, «l'âge» fait partie d'une étiquette non mutable. La bonne façon de travailler consiste à utiliser une variable mutable, comme dans l'exemple suivant:
comme clair, à partir de la référence de variable mutable (c'est-à-dire 'personB'), il est possible de modifier le champ de classe mutable 'age'.
J'insisterais encore sur le fait que tout vient de la différence mentionnée ci-dessus, qui doit être claire à l'esprit de tout programmeur Scala.
la source
personA
et al. semble éteint. Que la modification duage
membre fonctionne ou non est indépendante du fait que vous utilisezdef personA
ouvar personB
. La différence est que dans ledef personA
cas où vous modifiez l'Person
instance renvoyée par votre première évaluation depersonA
. Cette instance est modifiée, mais ce n'est pas ce qui est renvoyé lorsque vous évaluez à nouveaupersonA
. Au lieu de cela, la deuxième fois que vous faites,personA.age
vous faites effectivementnew Person("Tim",25).age
.Avec
vous définissez une fonction / variable paresseuse qui renvoie toujours une nouvelle instance de Person avec le nom "Kumar" et l'âge de 12 ans. Ceci est totalement valide et le compilateur n'a aucune raison de se plaindre. L'appel de person.age renverra l'âge de cette instance Person nouvellement créée, qui est toujours de 12.
Lors de l'écriture
vous attribuez une nouvelle valeur à la propriété age dans la classe Person, qui est valide puisque age est déclaré comme
var
. Le compilateur se plaindra si vous essayez de réaffecterperson
avec un nouvel objet Person commela source
Pour fournir une autre perspective, "def" dans Scala signifie quelque chose qui sera évalué à chaque fois qu'il sera utilisé, tandis que val est quelque chose qui est évalué immédiatement et une seule fois . Ici, l'expression
def person = new Person("Kumar",12)
implique que chaque fois que nous utilisons "personne", nous recevrons unnew Person("Kumar",12)
appel. Il est donc naturel que les deux "person.age" ne soient pas liés.C'est ainsi que je comprends Scala (probablement d'une manière plus "fonctionnelle"). Je ne sais pas si
c'est vraiment ce que Scala entend signifier. Je n'aime pas vraiment penser de cette façon au moins ...
la source
Comme Kintaro le dit déjà, person est une méthode (à cause de def) et renvoie toujours une nouvelle instance de Person. Comme vous l'avez découvert, cela fonctionnerait si vous changez la méthode en var ou val:
Une autre possibilité serait:
Cependant,
person.age=20
dans votre code est autorisé, lorsque vous récupérez unePerson
instance de laperson
méthode, et sur cette instance, vous êtes autorisé à modifier la valeur de avar
. Le problème est qu'après cette ligne, vous n'avez plus de référence à cette instance (car chaque appel àperson
produira une nouvelle instance).Cela n'a rien de spécial, vous auriez exactement le même comportement en Java:
la source
Prenons ceci:
et réécrivez-le avec un code équivalent
Voyez,
def
est une méthode. Il s'exécutera chaque fois qu'il sera appelé, et à chaque fois il retournera (a)new Person("Kumar", 12)
. Et ce n'est pas une erreur dans l '"affectation" car ce n'est pas vraiment une affectation, mais juste un appel à laage_=
méthode (fournie parvar
).la source