В scala множественном наследовании, как разрешать конфликтующие методы с одной и той же сигнатурой, но с другим типом возврата?

Рассмотрим приведенный ниже код:

trait A {
  def work = { "x" }
}

trait B {
  def work = { 1 }
}

class C extends A with B {
  override def work = super[A].work
}

Класс C не будет компилироваться в scala 2.10, из-за "переопределения работы метода в признаке A типа = > String; работа метода имеет несовместимый тип".

Как выбрать один конкретный метод?

Ответы

Ответ 1

Я боюсь, что это невозможно. super[A].work работает только в том случае, если A и B имеют одинаковые типы возврата.

Рассмотрим это:

class D extends B

....

val test: List[B] = List(new C(), new D())
test.map(b => b.work) //oops - C returns a String, D returns an Int

Ответ 2

Вы не можете этого сделать.

Посмотрите на этот фрагмент кода:

val c = new C
val a: A = c
val b: B = c

Невозможно, чтобы обе эти линии могли работать:

val s: String = a.work
val i: Int = b.work

Если мы разрешили компиляцию такого кода, одно из этих назначений должно было бы выбросить ClassCastException или потерпеть неудачу другим способом. Таким образом, просто невозможно разрешить такой конфликт.

Я думаю, вам нужно обходить это с помощью какой-то формы делегирования, возможно, что-то вроде этого:

class C extends A {
  def toB = new B {
    //implement B methods by somehow delegating them to C instance
  }
}

Ответ 3

Scala просто мешает вам смешивать A и B вместе, если они объявляют метод с тем же именем и несовместимой сигнатурой.

Ответ 4

Вы не можете сделать это в Scala.

Способ работать с этим - использовать черты как соавторы

trait A {
  def work = { "x" }
}

trait B {
  def work = { 1 }
}

class C {
  val a = new A { }
  val b = new B { }

  a.work
  b.work
}