'val' или 'var', изменяемый или неизменный?
Я могу определить переменную (по 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
, так что происходит?
Ответы
Ответ 1
Компилятор ищет x.+= ...
, и если он не может его найти, он пытается преобразовать оператор в x = x + ...
(который выполняется только тогда, когда x
является var
или x
desugars в вызов некоторого метода update
). Так как immutable.Set
реализует оператор +
, а x
- это var
, это удается.
Ответ 2
Исходный неизменяемый набор не изменяется.
Продолжая Кен ответ, + создал новый набор, добавил новый элемент и вернул новый набор, оставив исходный заданный объект без изменений. Таким образом, вы могли бы сказать 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)
Get:
> Set("aaaaaa","bbbbbb","cccc")
> Set("aaaaaa","bbbbbb","cccc")
Voila.