'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
так что происходит?
2 ответа
Компилятор ищет x.+= ...
и, если он не может его найти, он пытается преобразовать выражение в x = x + ...
(который только успешно, если x
это var
, или же x
Desugars в вызов некоторых update
метод). поскольку immutable.Set
реализует +
оператор и x
это var
это удается.
Оригинальный неизменный набор все еще остается неизменным.
Продолжая ответ Кена, + создал новый набор, добавил новый элемент и возвратил новый набор, оставив исходный объект набора без изменений. Так что можно сказать 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
, то вы не можете переназначить его на новый адрес.
Если вы использовали изменяемый набор, то x
а также y
будет указывать на тот же объект, потому что +
call добавил бы существующий набор, а не возвращал новый (будучи изменяемым...):
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")
Вуаля.