class Person(val name:String,var age:Int )
def person = new Person("Kumar",12)
person.age = 20
println(person.age)
Эти строки кода выводятся 12
, хотя person.age=20
были успешно выполнены. Я обнаружил, что это происходит, потому что я использовал def в def person = new Person("Kumar",12)
. Если я использую VAR или VAL, вывод 20
. Я понимаю, что по умолчанию это значение val в scala. Это:
def age = 30
age = 45
... выдает ошибку компиляции, потому что это значение по умолчанию. Почему первый набор строк выше не работает должным образом, и все же также не ошибается?
val
может быть изменено, но объект, на который ссылается val, не может. Аval
не является константой.List
какfinal
, но можете изменить его содержимое.Я бы начал с различия, которое существует в Scala между def , val и var .
def - определяет неизменяемый ярлык для содержимого правой стороны, которое лениво оценивается - оценивается по имени.
val - определяет неизменяемую метку для правого содержимого, которое охотно / немедленно оценивается - оценивается по значению.
var - определяет изменяемую переменную , изначально установленную на оцениваемое содержимое правой стороны.
Пример, определение
Пример, вал
Пример, вар
В соответствии с вышесказанным, метки от def и val не могут быть переназначены, и в случае любой попытки появится ошибка, подобная приведенной ниже:
Когда класс определен как:
и затем создается с помощью:
для этого конкретного экземпляра Person создается неизменяемый ярлык (т. е. personA). Всякий раз, когда необходимо изменить изменяемое поле 'age', такая попытка завершается неудачно:
как и ожидалось, age является частью неизменяемой метки. Правильный способ работы с этим заключается в использовании изменяемой переменной, как в следующем примере:
как ясно, из ссылки на изменяемые переменные (то есть 'personB') можно изменить изменяемое поле класса 'age'.
Я бы все-таки подчеркнул тот факт, что все проистекает из вышеуказанного различия, которое должно быть понятно любому программисту Scala.
источник
personA
соавт. кажется выключеннымage
Работает ли изменение члена или нет, не зависит от того, используете ли выdef personA
илиvar personB
. Разница в том, что вdef personA
случае, если выPerson
изменяете экземпляр, возвращенный после первой оценкиpersonA
. Этот экземпляр будет изменен, но это не то , что возвращается , когда вы в очередной раз оценитьpersonA
. Вместо этого, во второй раз, вы делаетеpersonA.age
это эффективноnew Person("Tim",25).age
.С участием
вы определяете переменную function / lazy, которая всегда возвращает новый экземпляр Person с именем "Kumar" и возрастом 12. Это полностью допустимо, и у компилятора нет причин жаловаться. Вызов person.age вернет возраст этого вновь созданного экземпляра Person, который всегда равен 12.
При написании
Вы присваиваете новое значение для свойства age в классе Person, которое является действительным, поскольку возраст объявлен как
var
. Компилятор будет жаловаться, если вы попытаетесь переназначитьperson
новый объект Person, напримеристочник
Чтобы представить другую перспективу, «def» в Scala означает то, что будет оцениваться каждый раз, когда он используется, тогда как val - это то, что оценивается сразу и только один раз . Здесь выражение
def person = new Person("Kumar",12)
влечет за собой то, что всякий раз, когда мы используем «лицо», мы получимnew Person("Kumar",12)
вызов. Поэтому естественно, что два «персонажа» не связаны между собой.Я так понимаю Scala (возможно, в более «функциональной» манере). Я не уверен, если
Это действительно то, что Скала намеревается иметь в виду, хотя. Мне не очень нравится так думать, по крайней мере ...
источник
Как уже сказал Кинтаро, person - это метод (из-за def), который всегда возвращает новый экземпляр Person. Как вы узнали, это будет работать, если вы измените метод на var или val:
Другая возможность будет:
Тем не менее,
person.age=20
в вашем коде это разрешено, так как вы возвращаетеPerson
экземпляр изperson
метода, и в этом случае вам разрешено изменять значение avar
. Проблема в том, что после этой строки у вас больше нет ссылки на этот экземпляр (так как каждый вызовperson
создаст новый экземпляр).В этом нет ничего особенного, у вас будет точно такое же поведение в Java:
источник
Давайте возьмем это:
и переписать его с эквивалентным кодом
Видите,
def
это метод. Он будет выполняться каждый раз, когда вызывается, и каждый раз будет возвращать (a)new Person("Kumar", 12)
. И это не ошибка в «присваивании», потому что на самом деле это не присваивание, а просто вызовage_=
метода (предоставленногоvar
).источник