2017-02-07 12 views
0

Я работаю над проектом, который в основном требует множественного наследования в формальном смысле:Симуляция множественного наследования в Scala

class X 
class Y 

class XY extends X,Y 

У меня есть два класса, которые имеют некоторые определения и используемые в коде, то есть:

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

Я хочу, чтобы динамически создать класс XY, который просто объединяет все определения из X и Y, но по-прежнему сохраняет безопасность типов. Более конкретно, что ранее определенные alpha и beta по-прежнему принимают этот объединенный класс.

Я знаю, что Scala позволяет смешивать в чертах, например:

trait T 
class A 

val ta = new A with T 

Это работает отлично.

Однако, я не могу сделать это с классами:

class X 
class Y 

val xy = new X with Y 

Как with .. должна быть черта.

Я попытался обойти это, выполнив следующие действия:

trait xV extends X 
trait yV extends Y 

val xy = new xV with yV 

К сожалению, это не работает и выдает следующую ошибку:

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 

Любая помощь будет оценена.

Edit:

Чтобы уточнить, я не может изменить классы X или Y.

ответ

2

Doing это буквально невозможно. Но

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

Это конкретное требование может быть достигнуто с помощью неявного преобразования:

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 
} 

Вы также будете иметь возможность вызывать X «S и Y» методы s непосредственно.

Но, к примеру,xy match { case x: X => ... не будет соответствовать, и аналогичным образом xy.isInstanceOf[X] будет ложным. Если X или Y переопределить любой из методов Object: equals, hashCode, или toString, они не будут унаследованы XY.

+0

Это может быть очень полезно. Я отчитаю. Большое спасибо. – Crembo

+0

Ну, похоже, это решение работает в некоторой степени ... Но есть ли способ сделать преобразование 'toX' более приоритетным, чем' toY'? – Crembo

+0

Да, просто переместите 'toY' в свойство, которое' object XY' расширяет. –

2

Scala не имеет многообразия наследования типа C++, чтобы избежать страшного шаблона наследования Diamond Shape.

(0) solution, предоставленный компанией Scala, представляет собой смесины в виде Trait. Чтобы разрешить конфликты реализации метода, выбран последний префикс (тот, который больше всего справа).

Таким образом, если, по крайней мере, один из X или Y не является Черта, A не сможет наследовать (методы) и от