2014-02-13 20 views
4

下面的代碼從這個職位是採取:How to create Scala swing wrapper classes with SuperMixin?Scala包裝類通過擴展組件和SequentialContainer.Wrapper特質,我對特質有正確的理解嗎?

import scala.swing._ 
import javax.swing.JPopupMenu 

class PopupMenu extends Component with SequentialContainer.Wrapper { 
    override lazy val peer: JPopupMenu = new JPopupMenu with SuperMixin 

    def show(invoker: Component, x: Int, y: Int): Unit = peer.show(invoker.peer, x, y) 
} 

我一直在試圖使定製包裝,以便需要明白這一點,這是很簡單的,但由於 我纔剛剛開始想結識斯卡拉,所以我有點不確定特徵。所以我聽到的是,特質就像多重繼承,你可以混合搭配它們?

我畫了一張圖表示PopupMenu在整個繼承結構中的位置。只是爲了澄清一些事情:

1)它似乎重寫了懶惰val peer:JComponent從組件,也從SequentialContainer.Wrapper獲取內容屬性? (紫色文字)是嗎?

2)Sequential.Wrapper也有一個抽象的def peer:JComponent ..但是這不是被override的,所以在這裏它不被使用?

3)令人困惑的是Component和Sequential.Wrapper有一些相同的屬性:它們都有def publish和def subscribe(紅色文本)..但popupMenu將使用的屬性是從Component中訂閱/發佈類?

4)爲什麼我們不能編寫PopupMenu使用Component擴展SequentialContainer.Wrapper?

希望這一次不是太多問題。幫助會非常讚賞,我是一個初學者斯卡拉.. diagram representing the inheritance/trait relationship leading up to popupMenu

回答

2

我來回答使用您的問題的數字:

  1. 正確

  2. 正確的。最大的特點是UIElement,它定義了摘要成員def peer: java.awt.Component。那麼你有Container,它只是增加摘要成員def contents: Seq[Component]能夠讀取子組件。 Container.Wrapper具體Container的實現,它假設(抽象地)Java對等點是javax.swing.JComponent。請注意,在Java自己的層次結構中,javax.swing.JComponentjava.awt.Component的子類型,因此不存在衝突。子類型可以改進其成員的類型(「協方差」)。 SequentialContainer通過說contents可變緩衝區(而不是隻讀序列)來改進Container。因此,它的實現SequentialContainer.WrapperContainer.Wrapper中混合,但是用標準Scala緩衝區代替contents。在任何時候都沒有給出具體的peer。爲了方便起見,Component確實實現了該成員,但正如您所見,最終類PopupMenu覆蓋了peer。由於類型系統的工作方式,所有參與特徵都可以訪問peer,但只有PopupMenu「知道」該類型已被提煉爲javax.swing.JPopupMenu。例如SequentialContainer.Wrapper只知道有一個javax.swing.JComponent,所以它可以使用這部分對等的API。

  3. Publisher特徵是由UIElement引入的,所以你會發現它來自UIElement派生的所有類型。 在層次結構中多次出現相同的特徵沒有任何問題。在最後一堂課中,只有一個Publisher的實例,它不存在多個「版本」。即使Publisher尚未在根目錄中定義,但是在例如ComponentSequentialContainer.Wrapper中獨立定義,您將只在最終課程中獲得一個實例。

  4. 這是一個容易的。在Scala中,你只能擴展一個類,但可以混合使用任意數量的特性。 Component是一類,而其他所有東西都是特質。它是class A extends <trait-or-class> with <trait> with <trait> ...


綜上所述,所有GUI元素從性狀UIElement其由java.awt.Component備份繼承。具有子元素的元素使用特徵Container,以及允許您按特定順序添加和移除元素的所有正常面板類型元素使用SequentialContainer。 (並非所有面板都有連續順序,例如BorderPanel沒有)。這些是抽象接口,爲了獲得所有必要的實現,您有.Wrapper類型。最後得到一個可用的類,你有Component其中擴展UIElement,並要求對方是javax.swing.JComponent,所以它可以實現所有的標準功能。

當實現一個新的包裝時,通常使用Component和細化peer類型,這樣就可以訪問對等體(例如的JPopupMenushow方法)的特定功能。