如何让具有相同基本特征的多个特征实现相同的方法

How to have multiple traits of same base trait implement the same method

我有一个场景,其中多个特征继承自一个固定的基本特征。基本特征有一个抽象方法,每个都需要实现。使用这些traits的class也需要实现这个方法:

trait A {
    def f: Any
}

trait B1 extends A {
    val i: Int
    override def f: Any = println("B1: " + i)        
}

trait B2 extends A {
    val j: Int
    override def f: Any = println("B2: " + j)
}

class C extends A with B1 with B2 {
    val i = 1
    val j = 2

    override def f: Any = {
        super.f
        println("C::f")
    }
}

然后当我做一个

new C().f

只输出"B1: 1"不输出"B2: 2"

有没有一种方法可以定义 B1、B2 和 C,以便可以调用 f 的所有实现?

这是 diamond problem 的一个例子,Scala 通过 线性化 的过程解决了这个问题:

Scala resolves method names using a right-first depth-first search of extended 'traits', before eliminating all but the last occurrence of each module in the resulting list. So, the resolution order is: [D, C, A, B, A], which reduces down to [D, C, B, A].

所以输出应该符合你的情况

B2: 2
C::f

所以似乎无法在 B1B2 中调用所有 f 覆盖,而只有 B2.f 被解析。

你知道你混合了哪两个钻石特征,你可以调用两个 super 实现并指定你想要调用每个 super 的特征 实施。

所以,您可以这样实现 C

class C extends A with B1 with B2 {
  val i = 1
  val j = 2

  override def f: Any = {
    super[B1].f
    super[B2].f
    println("C::f")
  }
}

并且会得到输出:

B1: 1
B2: 2
C::f