不相关的 Scala 中的变量可见性 类

Variable visibility in unrelated scala classes

问题是C trait如何使用D class中指定的str字段。 D 从 A 扩展,因此它没有在任何合同中指定 str 。即使 C 能够使用它。当我从 D 中删除 str 时,编译器不会编译此代码。它怎么知道 D 中的 str 与 B 中的 str 无关是同一回事。我希望在动态类型语言中有这种行为,但在静态类型语言中不会。

trait A {
  def receive(): PartialFunction[String, Any]
}

trait B extends A {
  def str: String
}

trait C extends B {
  abstract override def receive(): PartialFunction[String, Any] =
    cReceive.orElse(super.receive())

  val cReceive: PartialFunction[String, Any] = {
    case "MemberUp" ⇒ s"$str"
  }
}

class D extends A {
  override def receive(): PartialFunction[String, Any] = {
    case _ ⇒
  }

  def str: String = "My string"
}

class E extends D with C

object Main extends App {
  private val e = new E
  println(e.receive().apply("MemberUp"))
}

魔法正在 E 中发生。

基本上B说"there is going to be a method str returning string"。现在,当它在 C 中被调用时,会查看一个实现。

如果 E 定义了 str 那么一切就都清楚了。在这种情况下,str 取自 D。当编译器构建 E 时,它首先定义哪些方法可用,然后按照线性化定义的顺序查找实现(参见 )。这意味着一个实现是可用的,就好像它是在 E 中定义的一样(因为 def str 是 E.

的一部分

注意:如果您将 D 中的 recieve 更改为 return 其他内容,则 str 仍将被 returned。这是因为从线性化顺序来看,C 实现先于 D,并且 D 成为 C 的超类。