'val' или 'var', изменчивый или неизменный? - PullRequest
13 голосов
/ 22 февраля 2011

Я могу определить переменную (var), которая является неизменной:

var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
x += "cccc"
println(x.isInstanceOf[scala.collection.immutable.Set[String]])

Это приводит к:

true
true

+= метод не является членом scala.collection.immutable.Set, так что же происходит?

Ответы [ 2 ]

22 голосов
/ 22 февраля 2011

Компилятор ищет x.+= ..., и, если он не может его найти, он пытается преобразовать инструкцию в x = x + ... (что успешно, только если x - это var или x десугары в вызов некоторого update метода). Поскольку immutable.Set реализует оператор +, а x является var, это успешно выполняется.

6 голосов
/ 23 февраля 2011

Исходный неизменный набор все еще не изменился.

Продолжение Ответ Кена , + создал новый набор, добавил новый элемент и возвратил новый набор, оставив исходный объект набора без изменений. Таким образом, вы можете сказать var y = x; y += "cccc", и у вас будет 2 комплекта вместо 1:

var x = scala.collection.immutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
println(y.isInstanceOf[scala.collection.immutable.Set[String]])

Начало:

> true
> Set(aaaaaa, bbbbbb)
> Set(aaaaaa, bbbbbb, cccc)
> true
> true

Вы видите, что сама структура данных все еще неизменна, но поскольку вы объявили var, присваивание является изменяемым. Таким образом, он может быть переназначен на новый объект, если он возвращается. Если вы измените объявление x как val, вы не сможете переназначить его на новый адрес.

Если бы вы использовали набор mutable , тогда x и y указывали бы на один и тот же объект, потому что вызов + добавил бы существующий набор вместо возврата нового ( будучи изменчивым ...):

var x = scala.collection.mutable.Set("aaaaaa","bbbbbb")
println(x.isInstanceOf[scala.collection.immutable.Set[String]])
var y = x
y += "cccc"
println(x)
println(y)

Получить:

> Set("aaaaaa","bbbbbb","cccc")
> Set("aaaaaa","bbbbbb","cccc")

Вуаля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...