В множественном наследовании 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; работа метода имеет несовместимый тип".

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

4 ответов


боюсь, что это невозможно сделать. The 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

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


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

посмотрите на этот кусок кода:

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
  }
}

вы не можете сделать это в 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
}