2014-05-23 84 views
0

我期待一個編譯器錯誤,用下面的代碼:澄清斯卡拉VAR和Val

object Test { 
    def main(args: Array[String]) : Unit = { 
    val x = 10 
    var y = x 
    val z = y 

    println("x: " + x) 
    println("y: " + y) 
    println("z: " + z) 

    y = 100 

    println("x: " + x) 
    println("y: " + y) 
    println("z: " + z) 
    } 
} 

但是,代碼編譯,我得到以下的輸出:

x: 10 
y: 10 
z: 10 
x: 10 
y: 100 
z: 10 

這是怎麼回事上?

當您將val初始化爲可變值(反之亦然)時,是否立即複製它?它是否爲任何課程做到這一點?這是一個很深的副本嗎?

回答

2

您的示例行爲與C,java,python或任何其他編程語言完全相同。

我想你真的在問val/var不可變/可變的區別。這裏有一個更清楚的例子:

class A(var s: String) { 
    override def toString = s 
} 

val x = new A("first") // a new A object [Object1] is allocated, x points to it 
var y = x     // y is pointed to x's referent, which is [Object1] 
val z = y     // z is pointed to y's referent, which is [Object1] 

println(x) // "first" 
println(y) // "first" 
println(z) // "first" 

y = new A("second")  // a new A object [Object2] is allocated, y points to it 

println(x) // "first" // note that x is still pointing to the same object [Object1] 
println(y) // "second" 
println(z) // "first" // so is z 

x.s = "third"    // the string *inside* [Object1] is changed 

println(x) // "third" // x still points to [Object1], which now contains "third" 
println(y) // "second" // y still points to [Object2] 
println(z) // "third" // z still points to [Object1], which now contains "third" 

y =總是會在一個新的對象指向y,而不是當前對象改變y點。這意味着說y =永遠不會更改xz

如果A是不可變的(class A(s: String)),那麼唯一的區別是操作x.s =將被禁止。上面的所有內容都完全一樣。

+0

這不回答我的問題。 – Emil

+1

查看我的更新。我做了一個新的例子,它實際上顯示了val/var和immutable/mutable之間的區別。 – dhg

+0

我會爭辯說,它實際上*顯示了val和var *之間的區別:在val的情況下,如果您嘗試在'y = new A(「second()中使用'x'來代替'y',則會出現編譯錯誤「)',目前還不清楚爲什麼你聲明值類型與參考值之間的行爲沒有區別 –

3

對於值類型(Int,Char,Double,...),val在引用類(包括String)和不可變值(在賦值時被複制,不共享)的情況下是實例的不可變引用。

變種是可變的引用和可變值分別

其實Java和許多其他語言有着非常相同的語義

+0

啊!說得通。謝謝! (當我允許時,我會選擇你的答案。) – Emil

+0

我想我的困惑是我的印象是Scala沒有價值類型。一切都是一堂課。我想我錯了。 – Emil

+0

它與值類型和類無關。如果你用一些帶有可變字段的類替換int,它將表現相同。 – dhg