2014-04-02 39 views
1

我正在編寫一個包裝類,它將大多數調用傳遞給根對象,並且我意外地將完整定義(帶有參數名稱x等)留在下面。令我驚訝的是,它編譯。那麼這裏發生了什麼?這與分配給root.p_相似嗎?我感到很奇怪,我可以在分配中留下「x」這個名字。另外,傳遞包裝呼叫的最佳(最快)方式是什麼?或者它沒有區別?這是爲什麼編譯和發生了什麼?

trait A { 
    def p(x:Int) = println("A"+123) 
} 

case class B(root:A) { 

    def p(x: Int): Unit = root.p(x:Int) // WHAT HAPPENED HERE? 
} 

object Test extends App { 
    val temp = new A{} 
    val b = B(temp) 
    b.p(123) 
} 

回答

2

什麼情況是類型歸屬,在這裏,它是沒有多少。

代碼工作就像你寫

def p(x: Int): Unit = root.p(x) 

,你打算。當你在調用中寫入x: Int(不是在聲明中,它具有完全不同的含義時)或更一般的expr: Type,它與expr具有相同的值,但它告訴編譯器檢查expr是否爲給定類型這是一個編譯類型的檢查,類似於upcast,根本不是一個運行時檢查,如asInstanceOf[...]),並將其視爲具有該類型。這裏,x確實是一個Int,它已經被編譯器視爲一個Int,所以歸屬不會改變。

除了在代碼某處記錄一個非顯而易見的類型,類型歸屬可用於重載的方法之間進行選擇:

def f(a: Any) ... 
def f(i: Int) ... 

f(3) // calls f(i: Int) 
f(3: Any) // calls f(a: Any) 

注意,在第二呼叫,與歸屬,編譯器知道3是類型爲Any,不如Int精確,但仍然如此。那將是一個錯誤,否則,這不是演員。但歸屬使其稱爲f的其他版本。

你可以看看這個問題的答案了更多的細節:https://stackoverflow.com/a/2087356/754787

+0

很棒的答案!現在我也明白爲什麼這個語法可能有用...... – LaloInDublin

0

你委託的B.pA.p執行?

我沒有看到除root.p(x:Int)以外的任何異常,您可以通過root.p(x)保存輸入。

特點是代碼混入的方式,我認爲最簡單的方法是:

trait A { 
    def p(x: Int) = println("A" + x) 
} 

case class B extends AnyRef with A 

val b = B() 
b.p(123) 
+0

感謝,我的例子只是爲了表現出較大的一段代碼。 – LaloInDublin