2011-04-29 22 views
3

爲了簡化我的實際代碼假設有兩個班,一個接一個的子類:scala:將子類實現重用爲兩個不同類的子類?

class Chair { 
    val canFold = false; 
    // ... 
} 

class FoldableChair extends Chair { 
    val canFold = true; 
    // ... 
} 

,在我執行我將有可能影響數百主席的其他子類或FoldableChair的:

class Armchair extends ... {} 
class DeckChair extends ... {} 
//... etc 

對於這些子類中的每一個,假設每個子類都有很長的實現,但我希望能夠讓它有時擴展主席,有時會擴展FoldableChair - 而不重複代碼。我想這樣做,而不必擴展子類本身。這可能以某種方式嗎?我需要使用特質來做到這一點嗎?

我也想創建一個有時會擴展主席的子類的特定實例,有時會擴展FoldableChair,但是當實例化它時會做出該選擇。這可能嗎?謝謝!

編輯:爲了澄清,我真正想要的是這樣的:

class Armchair extends Chair {} 

class ArmchairFoldable extends FoldableChair {} 

但扶手椅及ArmchairFoldable的實施是完全一樣的。也就是說,我想不重複他們的實現。

+0

我建議你閱讀這篇文章:http://www.artima.com/scalazine/articles/stackable_trait_pattern.html – 2011-04-29 12:29:12

回答

5

您可以使用實現特徵;也就是說,您可以混入一門課,併爲其他成員提供實施。

例子:

class Chair { 
    // you can use a def rather than a val as it's constant and 
    // and doesn't need to occupy a field 
    def canFold = false 

    // ... 
} 

class FoldableChair extends Chair { 
    override def canFold = true 
    // ... 
} 

trait Extensible extends Chair { 
    // this trait extends Chair to mean that it is only 
    // applicable to Chair or subclasses of Chair 
    def extend = /* ... */ 
} 

class FoldableExtensibleChair extends FoldableChair with Extensible 

然後,你可以寫:

val a = new Chair // bare-bones chair 

// decide at creation time that this one is extensible 
val b = new Chair with Extensible 

val c = new FoldableChair // non extensible 

// use predefined class which already mixes in Extensible 
val d = new FoldableExtensibleChair 
+0

而不是「特質Extensible extends Chair」來強制執行'Extensible'只適用於'Chair',是不是習慣於使用自我類型? '特質Extensible {self:Chair => ...}'不是100%肯定的折衷。只是問問。 – overthink 2011-04-29 15:15:50

+0

@overthink是的,在這種情況下習慣使用自我類型。 – 2011-04-29 19:47:57

+0

「擴展椅子」風格在Bill Venners的文章中與Frank Thomas聯繫在一起,並且在Scala編程書中更突出。看到這個問題,丹尼爾提供了一個非常好的答案:http://stackoverflow.com/questions/1990948/what-is-the-difference-between-scala-self-types-and-trait-subclasses – 2011-04-29 21:29:12