2013-01-05 114 views
6

我有一個抽象基類(Base),其具有用於將其(StackingTrait)定義了一些堆疊性狀。斯卡拉:性狀密新與抽象基類

trait Base { 
    def foo 
} 
trait StackingTrait extends Base { 
    abstract override def foo { super.foo } 
} 

這將是實現使用下面的語法子很方便,但是,這並不工作,因爲編譯器說,FOO需要與override,然後被宣佈與abstract override上重新編譯,這是無效的,因爲Impl是一類。

class Impl extends Base with StackingTrait { 
    def foo {} 
} 

我想不出爲什麼這樣的語法將被禁止的好理由; foo在邏輯上用Impl定義,以便在概念上進行堆疊的順序保持不變。

注意: 我想出了這種解決方法,它將有效地做我想做的同樣的事情,但輔助類的必要性使我想要更好的解決方案。

class ImplHelper extends Base { 
    def foo {} 
} 
class Impl extends ImplHelper with StackingTrait 

爲什麼所需的語法不能編譯,是有一個優雅的解決方案嗎?

回答

4

我的理解是,儘管錯誤信息可能會令人困惑,但行爲是正確的。 foo被聲明爲在StackingTraitabstract override,因而在混合了StackingTrait必須有一個混凝土(未標記爲abstract)實施foo之前的任何具體類StackingTrait(相對於線性順序)。這是因爲super指特質之前的線性順序,所以肯定需要有一個具體的實施fooStackingTrait之前混入,或super.foo將是荒謬的。

當你這樣做:

class Impl extends Base with StackingTrait { 
    def foo {} 
} 

線性順序爲Base < - StackingTrait < - ImplStackingTrait之前的唯一特徵是BaseBase沒有定義foo的具體實現。

但是,當你這樣做:

traitImplHelper extends Base { 
    def foo {} 
} 
class Impl extends ImplHelper with StackingTrait 

的線性順序變爲:Base < - ImplHelper < - StackingTrait < - Impl 這裏ImplHelper包含foo一個具體的定義,並definitly StackingTrait之前。

值得一提的是,如果你在StackingTrait(如class Impl extends StackingTrait with ImplHelper)之後混合了ImplHelper,那麼你將再次遇到同樣的問題並且無法編譯。

因此,這看起來對我來說相當一致。 我沒有意識到按照您的意圖編譯它的方法。但是,如果您更關心的是使它更易於編寫Impl(並能夠定義foo在那裏,而不需要單獨的類/性狀)比使它容易寫BaseStackingTrait,你仍然可以做到這一點:

trait Base { 
    protected def fooImpl 
    def foo { fooImpl } 
} 
trait StackingTrait extends Base { 
    abstract override def foo { super.foo } 
} 

class Impl extends Base with StackingTrait { 
    protected def fooImpl {} 
} 

就像在原始版本中一樣,你強制每個具體類實現foo(以fooImpl的形式),並且這次它編譯。 這裏的缺點是,儘管fooImpl一定不能調用super.foo(它沒有任何意義,並且會進入無限循環),但編譯器不會警告您。

+0

很好的答案!我正要發佈關於這種情況的問題。謝謝! –

+0

我剛剛也遇到了這個問題。線性化對此最終是正確的,但我意識到堆疊特徵的真實世界目的是這樣的:您可以僅使用堆棧特徵對現有的通用抽象類/特徵的具體實現進行修改。 IE瀏覽器。有一個「抽象類List」和一個「特性Mod擴展列表」。你不能只寫'Foo類擴展List with Mod'。首先,你必須有一個具體的List,比如'class LinkedList extends List',然後你可以編寫'class Bar extends Mod'來擴展LinkedList。希望這是有道理的。 –

+0

我忘了補充一點,這只是關注'abstract override'方法的特性,要清楚。沒有這些方法,似乎特質可以自由混合。 –