2012-02-08 69 views
3
case class Test(kind: Int) { 
    val ifX = if (isX) "is X" else "not X" 
    val isX = kind == 1 
} 

val test = Test(1) 
println("ifX=%s, isX=%b".format(test.ifX, test.isX)) 

爲什麼這段代碼打印: IFX =不是X,ISX =真奇怪的行爲

當是舉 「VAL IFX」 之前 「IFX」 這是確定(打印IFX =爲X)

編輯:我知道如何解決這個問題。我不明白爲什麼編譯器不會在這種情況下發出警告或錯誤。

+3

不知道有關scala的任何信息,我會猜想ifX在isX之前被初始化。嘗試顛倒你的聲明的順序。 – 2012-02-08 20:41:29

回答

7

你正在做一個假設,順序在scala中無關緊要。它的確如此。因爲isX是一個變量值,並且在ifX運行時定義它,但它的值仍未初始化,因此它是其類型(布爾值,所以爲false)的默認值。

如果您將isX重新定義爲函數(def isX = ...),它將起作用。

這大致相當於以下Java:

class Test { 
    String ifX; 
    bool isX; // Defaults to false, its a primitive after all 
    public Test(Int kind) { 
     ifX = isX ? "is X" : "not X"; 
     isX = kind == 1; 
    } 
} 
+0

如果「isX」在「ifX」中單元化,爲什麼編譯器沒有警告或錯誤?爲什麼編譯器假設沒有定義==默認值,這對我來說很奇怪,我認爲這可能會導致錯誤 – 2012-02-08 21:14:41

+0

Scala是一個尖銳的工具,非常適合專家,可能對非專家很危險。我只能說「小心」。 http://codebetter.com/jefferypalermo/2007/12/02/who-is-to-say-that-my-knife-is-too-sharp-for-my-own-good/ – 2012-02-08 21:17:47

+0

您可以指向頁面「Scala參考」在哪裏定義了這種行爲?我在環顧四周,但找不到這個:/ – 2012-02-08 21:20:37

1

好,ISX是未定義類時遇到的第一次。 你能切換兩條線嗎?

7

正如Chris Shain指出的isX尚未定義。我只想補充一點,它不是一個變量,而是一個的值,這意味着你實際上可以讓它變懶。一個懶惰的值只在你需要的時候被實例化。理論上可以使ifXisX都變得懶惰。嘗試這樣的:

case class Test(kind: Int) { 
    val ifX = if (isX) "is X" else "not X" 
    lazy val isX = kind == 1 
} 

這應該給予所需的輸出。

7

OMG,我不知道多少次,我們會去通過這個...

這是不可能靜態檢測的東西比指數時間更好地在所有情況下使用不當向前引用。或者,如果是這樣,它已經足夠複雜,沒有人做到了。

這個特殊情況很簡單 - 沒有繼承,沒有擴展特性,沒有早期初始化器,沒有方法被調用,沒有關閉,沒有函數,沒有任何東西。很簡單,將來可能會添加警告。

您可以在運行時捕獲它,並且Scala爲此提供了-Xcheckinit標誌。

順便說一句,你可以在Java中得到完全相同的問題,雖然它在這個特別的情況下警告你。

+0

用於'-Xcheckinit'的+1 – leedm777 2012-02-08 23:07:03