Heinrich Schmetterling
Heinrich Schmetterling

Reputation: 6884

scala: reuse subclass implementation as a subclass of two different classes?

To simplify my actual code let's say there are two classes, one a subclass of the other:

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

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

and in my implementation I will have potentially hundreds of other subclasses of Chair or FoldableChair:

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

For each of these subclasses, suppose each one has a lengthy implementation but I want to be able to have it sometimes extend Chair and sometimes extend FoldableChair - without duplicating the code. I'd like to do so without having the subclass itself be extended. Is this possible somehow? Do I need to use traits to do this?

I'd also like to be able to create particular instances of a subclass which sometimes extend Chair and sometimes extend FoldableChair, but that choice is made when instantiating it. Is this possible too? Thanks!

Edit: to clarify, what I really want is this:

class Armchair extends Chair {}

class ArmchairFoldable extends FoldableChair {}

but the implementation of Armchair and ArmchairFoldable are exactly the same. That is, I'd like to not duplicate their implementations.

Upvotes: 3

Views: 226

Answers (1)

Jean-Philippe Pellet
Jean-Philippe Pellet

Reputation: 60006

You can use an implementation trait; i.e., a trait that you mix in with a class and that provides additional members with their implementation.

Example:

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

Then you can write:

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 

Upvotes: 5

Related Questions