2015-05-20 75 views
3

我正在閱讀Martin Odersky等人編寫的「Programming in Scala」中的特性章節(2ed),我對靜態綁定的類中的super聲明感到困惑,不像它在動態綁定的特性中(p。 220)。超類靜態綁定類嗎?

我明白這個說法,但是當涉及到例如像這樣的:

val queue = (new BasicIntQueue with Incrementing with Filtering) 

在第229頁或線性化(第234頁)的全部解釋,在我看來,那super不能靜態地因爲否則堆疊特徵將不可能 - 即當類「開始」已經解決了super堆疊方法的調用鏈時,無論用戶添加到特徵堆棧中,它都將直接觸擊父類。

我錯過了什麼? :-) super是否真的靜態綁定到它的父項?

+0

當你在堆棧類中調用'super'方法時,它總是在其中一個父特徵中調用一個特定的方法,對吧?編譯器知道對象的確切靜態類型,包括它繼承的所有特徵。就我所見,沒有任何東西可以阻止靜態調度。 –

+0

@VladimirMatveev,ad。 「堆疊班級中的方法」。該方法來自'BasicIntQueue'類,該方法是爲該類編寫和編譯的,而不知道將來如何使用它。然而'超級'被重新路由。正如我所說,也許我在這裏錯過了一些東西。 – greenoldman

+1

雖然此方法確實來自'BasicIntQueue',它在每個可堆棧特徵中都被覆蓋,這意味着每個特徵還包含此方法。你可以很容易地在'javap'輸出中找到它們。無論如何,對於非靜態方法,沒有像Java字節碼中的靜態分派那樣的東西。字節碼將包含用於常規方法的'invokevirtual'和用於接口方法的invokeinterface(用於構造函數的'invokespecial'和用於其他內容的invokedynamic')。這些方法仍然必須針對虛擬表格進行解析,除非使用了內聯等一些優化。 –

回答

1
val queue = (new BasicIntQueue with Incrementing with Filtering) 

在第229頁或線性化(第234頁)的全部解釋,在我看來,那超不能靜態綁定,否則堆疊特性是不可能的 - 即類「開始時, 「呼叫超級堆疊方法已經解決了的鏈條,這將打擊直接父類,無論加入特質

但是,在這種情況下,鏈棧哪些用戶不BasicIntQueue的方法開始,但與Filtering的。如果沒有混入特徵覆蓋該方法,它只會從類開始。如果定義,而不是

class MyQueue extends BasicIntQueue with Incrementing with Filtering { 
    .. // some super calls 
} 

// an anonymous class 
val queue = new BasicIntQueue with Incrementing with Filtering { 
    .. // some super calls 
} 

super將參考BasicIntQueue with Incrementing with Filtering,這是靜態解析。

然而,在Incrementingsuper調用動態解決的問題:BasicIntQueue with Incrementing他們將參考BasicIntQueue,而在BasicIntQueue with Filtering with Incrementing,他們將參考BasicIntQueue with Filtering,沒有任何變化Incrementing

+0

謝謝。我想我明白了 - 這是術語問題。因爲我認爲線性化就像「超級分辨率」表格的設置一樣。示例 - 讓'MyQueue'僅擴展'BasicIntClass',稍後將'queue'變量聲明爲'new MyQueue with Incrementing with Filtering'。人們可以認爲超級表的構建就在那裏(我的理解),但是你可以說超級是固定的,並且方法的順序是在那裏建立的。 – greenoldman