通常Scala是不可變的,你通常必須自己處理可變的情況。此外,case類本質上是不可變的,它們的複製方法是由編譯器生成的。所以是的,他們會分享相同的對象參考。這是不變性很好的原因之一。
你的第二個問題有點不同。在這種情況下,這些類是在單獨的環境中一個接一個地構建的。
這也是一個好主意,檢查什麼正在編譯:
>scalac -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package test {
class Foo extends Object {
private[this] val list: List = _;
<stable> <accessor> def list(): List = Foo.this.list;
def <init>(): b.Foo = {
Foo.super.<init>();
Foo.this.list = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
}
}
從這一點我們可以看出斯卡拉每次創建一個新的列表。此更改爲var
不會改變任何東西,我們可以檢查:
>scalac -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package test {
class Foo extends Object {
private[this] var list: List = _;
<accessor> def list(): List = Foo.this.list;
<accessor> def list_=(x$1: List): Unit = Foo.this.list = x$1;
def <init>(): b.Foo = {
Foo.super.<init>();
Foo.this.list = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
}
}
它只生成它(def list_=(x$1: List)
)setter方法。
如果您想引用同一個列表在兩種情況下,然後用對象的默認列表初始化:
object Foo {
val DefaultList = List(1,2,3,4,5,6)
}
class Foo {
var list = Foo.DefaultList
}
哪個編譯爲以下幾點:
>scalac -print test.scala
[[syntax trees at end of cleanup]] // test.scala
package test {
object Foo extends Object {
private[this] val DefaultList: List = _;
<stable> <accessor> def DefaultList(): List = Foo.this.DefaultList;
def <init>(): test.Foo.type = {
Foo.super.<init>();
Foo.this.DefaultList = immutable.this.List.apply(scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3, 4, 5, 6}));
()
}
};
class Foo extends Object {
private[this] var list: List = _;
<accessor> def list(): List = Foo.this.list;
<accessor> def list_=(x$1: List): Unit = Foo.this.list = x$1;
def <init>(): test.Foo = {
Foo.super.<init>();
Foo.this.list = Foo.DefaultList();
()
}
}
}
正如你所看到的列表只創建一次,然後通過在每個Foo類實例化上分配的參考def DefaultList(): List
。
感謝您的回答!但我不確定「同一對象參考」的含義。如果案例類有4種混入特性,並且它們的回顯有5個字段,那麼複製時是否必須複製4 * 5 = 20個引用?或者只有4個參考?(更確切地說,當一個類混合在一個特質中,它是否具有來自特質的所有領域,或者僅僅是對特質的虛擬實例的參考?) –
好的,我看到你回答了你的問題: ) –