Crembo
Crembo

Reputation: 5448

Simulating multiple-inheritance in Scala

I am working on a project that basically requires multiple-inheritance in the formal sense:

class X
class Y

class XY extends X,Y

I have two classes which have some definitions and are used throughout code, i.e:

def alpha(x: X)
def beta(y: Y)

I want to dynamically create a class XY which is just merges all definitions from X and Y but still retains the type-safety. More specifically that the previously defined alpha and beta still accept this merged class.

I know that Scala allows mixing in traits, for example:

trait T
class A

val ta = new A with T

That works fine.

However, I cannot do it with classes:

class X
class Y

val xy = new X with Y

As the with .. must be a trait.

I have tried circumventing this by doing the following:

trait xV extends X
trait yV extends Y

val xy = new xV with yV

Unfortunately this does not work and gives the following error:

Error:(33, 26) illegal inheritance; superclass X
 is not a subclass of the superclass Y
 of the mixin trait yV
    val xy = new xV with yV

Any help would be appreciated.

Edit:

To clarify, I cannot modify classes X or Y.

Upvotes: 0

Views: 298

Answers (2)

Alexey Romanov
Alexey Romanov

Reputation: 170835

Doing this literally is impossible. But

More specifically that the previously defined alpha and beta still accept this merged class.

This specific requirement can be achieved by using implicit conversions:

class XY {
  val x = new X
  val y = new Y
}

object XY {
  implicit def toX(xy: XY): X = xy.x
  implicit def toY(xy: XY): Y = xy.y
}

You'll also be able to call X's and Y's methods directly.

But e.g. xy match { case x: X => ... won't match, and similarly xy.isInstanceOf[X] will be false. If X or Y override any of the Object methods: equals, hashCode, or toString, they won't be inherited by XY.

Upvotes: 2

Bruno Grieder
Bruno Grieder

Reputation: 29874

Scala does not have the multiple inheritance C++ style, in order to avoid the dreaded Diamond Shape inheritance pattern.

The (only) solution provided by Scala is to provide mixins in the form of Traits. To resolve method implementation conflicts, the last Trait implemented (the one the most to the right) is chosen.

So unless, at least one of X or Y is a Trait, A will not be able to inherit (methods) from both

Upvotes: 2

Related Questions