2013-02-09 3 views
1

Рассмотрим следующий пример:Mutable или Immutable Set?

scala> val myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 
<console>:9: error: reassignment to val 
       myset += 3 
        ^

scala> var myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 

scala> myset 
res47: scala.collection.immutable.Set[Int] = Set(1, 2, 3) 

В одном случае я могу добавить «АЛЕКС», а в другом я не могу. Я знаю разницу между val и var. Однако то, что меня смутило в обоих случаях, Скала говорит мне, что Набор неизменен, но он позволяет различное поведение.

Я не хочу так просто, потому что в oncase myset есть val, а в одном это var. Я хочу получить более глубокий ответ, чтобы объяснить, почему в обоих случаях Scala говорит, что myset является неизменным набором, но все же рассматривает оба по-разному. Потому что это счетчик интуитивно.

Например, существует ли какая-либо разница с использованием набора mutuable и объявления неизменяемого набора как var? И почему scala позволяет вам сгибать правила? Не было бы лучше, если бы это было сказано неизменным, это означало это?

Спасибо.

ответ

3

Прежде всего давайте переводить += вызов

val myset = Set(1,2) 
myset = myset + 3 //this is what the compiler does for myset += 3 

Это означает, что мы на самом деле вызов метода + на Set, чьи scaladoc говорит

Создает новый набор с дополнительный элемент, если элемент уже не присутствует. Поэтому

Что код пытается сделать, это создать новый Set с дополнительным элементом и переназначить его на неизменного ссылкиmyset.

Теперь, если мы изменим ссылку на изменяемый один (используя var), то вы можете передать его с новоиспеченными и неизменнымSet(1,2,3)

оригинального комплектом (1, 2) по-прежнему неизменен и нет правила сломан. Поясним это с футляром

var myset = Set(1,2) 
val holdIt = Some(myset) 
myset += 3 
println(myset) // will print Set(1, 2, 3) 
println(holdIt)// will print Some(Set(1, 2)) 

Как вы можете видеть, оригинальный Set, который захвачен Option, никогда не изменилась, мы просто переназначить это переменная ссылка на вновь созданный Set

2

Когда ты используйте неизменяемый Set, новый Set будет создан и переназначен на var, что невозможно при использовании val. Но изменяемый набор может быть мутирован. Хотя нижеследующий не совершенно сохранить демонстрацию, он все еще показывает, что с неизменным набором создается новый объект, а изменяемый Set экземпляр остается прежний:

scala> var set1 = Set(1, 2) 
set1: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> System.identityHashCode(set1) 
res0: Int = 2119337193 

scala> set1 += 3 

scala> System.identityHashCode(set1) 
res2: Int = 1866831260 

scala> var set2 = collection.mutable.Set(1, 2) 
set2: scala.collection.mutable.Set[Int] = Set(2, 1) 

scala> System.identityHashCode(set2) 
res3: Int = 594308521 

scala> set2 += 3 
res4: scala.collection.mutable.Set[Int] = Set(2, 1, 3) 

scala> System.identityHashCode(set2) 
res5: Int = 594308521 
2

Рассмотрим myset как указатель и Set(1,2) как объект

В случае val myset указатель присваивается только один раз & не может указывать на другой объект (т. Е.указателя неизменна), где в качестве в случае var myset может быть назначен произвольный раз & может указывать на различные объекты (т.е. указателя является изменяемым)

В обеих случаях объект Set(1,2) неизменно.

Когда вы

scala> val myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 
<console>:9: error: reassignment to val 
       myset += 3 
        ^

myset += 3 фактически дает новый Set с 3 приложенными к нему ..

Поскольку myset указателя неизменен вы не можете переназначить на новый object возвращаемого метода + ,

, где, как и в случае

scala> var myset = Set(1,2) 
myset: scala.collection.immutable.Set[Int] = Set(1, 2) 

scala> myset += 3 

Поскольку myset указателя изменчиво вы можете переназначить на новый object возвращаемого метода +.

Смежные вопросы