2011-04-29 57 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