2016-09-20 20 views
1

我不確定是否有可能,或者我在這裏問錯了問題。比方說,如果我有像我可以將可堆疊特徵邏輯移至父級?

trait Parent { 
    def foo : String = " Parent " 
} 

trait Child1 extends Parent { 
    override def foo : String = super.foo + " Child 1 " 
} 

trait Child2 extends Parent { 
    override def foo : String = super.foo + " Child 2 " 
} 

,並使用它像

class ChildGroup extends Child1 with Child2 
(new ChildGroup).foo 

結果如預期BE " Parent Child 1 Child 2 "

,但我發現很難維持,尤其是當別人用我的特質並沒有按照我的意思使用它

trait Child3 extends Parent //<-- not override foo, and no error 

trait Child4 extends Parent { 
    override def foo : String = " Child 4 " //<-- forget super.foo + 
} 

和使用像

class ChildGroup extends Child1 with Child2 with Child3 with Child4 
(new ChildGroup).foo 

結果將只是" Child 4 ",我不希望這樣的事情發生我只是希望它永遠堆棧

所以這將是很好的堆棧特質的所有邏輯轉移到Parent

有沒有可能這樣做?或者還有其他選項會迫使其他人總是這樣做super.foo + x

+0

您可能可以使用宏或編譯器插件強制調用'super',但這通常不是一個好主意。即使你強制調用'super.foo',也不能保證它能正確使用。它被稱爲_semantic binding_,應該避免它,因爲它需要客戶端代碼來知道它正在實現的代碼的語義 - 這應該不會讓人感到意外,它會導致錯誤。也許有一種巧妙的方法來在「Parent」中封裝你想要的內容,但它可能比前者更醜陋。 –

+0

同意,我不想要宏或插件。只希望有人會有可接受的醜陋解決方案 – izht

回答

1

這是面向對象的問題。

您可以定義父爲:

trait Parent{ 
    public final def f():String= { 
       "Parent" +g(); 
    } 
    protected abstract def g():String 
} 

trait Child extends Parent{ 
    def g()= "Child" 
} 

執行父功能獨生子女之前先運行。如果您有多個孩子,並且您希望在調用某個函數時應用所有這些功能,我認爲使用這種mixin技術是濫用行爲,但這不是此技術的目的(添加功能)。

如果你想添加功能的功能,請看看修飾器設計模式。

關於trait Child3 extends Parent //<-- not override foo, and no error使用reular編碼是不可能的。你可以定義宏,但我不會建議它,因爲它是實驗性的,這意味着它可以從scala sdk中移除。

相關問題