为什么抽象方法有时需要覆盖?

Tim*_*Tim 5 scala

基于上一个问题,以下代码编译正常

trait Logger {
  def log(msg: String): Unit
}

trait LoggerA extends Logger {
  def log(msg: String) = ???
}

trait LoggerB extends Logger {
  override def log(msg: String) = ???
}

class Logged1 extends LoggerA 
class Logged2 extends LoggerB
class Logged3 extends LoggerA with LoggerB
Run Code Online (Sandbox Code Playgroud)

override不要求LoggerA ,因为没有具体的实施logLogger

但是,如果我override从中删除LoggerB不再编译:

class Logged3 inherits conflicting members:
  def log(msg: String): Nothing (defined in trait LoggerA) and
  def log(msg: String): Nothing (defined in trait LoggerB)
  (note: this can be resolved by declaring an `override` in class Logged3.)
Run Code Online (Sandbox Code Playgroud)

为什么override在这种特定情况下需要?指定是否会override以某种方式更改方法或类?

Mar*_*lic 3

我猜它是由SLS 5.1.4 Overriding指定的

\n
\n

如果 M\xe2\x80\xb2 不是抽象成员,则 M 必须标记为override.\n... 或者 M 和 M\xe2\x80\xb2 都覆盖在 a 中定义的第三个成员 M\'\' \n包含 M 和 M\' 的类的基类。

\n
\n

同样在第 5.1.3 节“类成员”中,也有与 OP 类似的 override 使用

\n
trait A { def f: Int }\ntrait B extends A { def f: Int = 1 ; def g: Int = 2 ; def h: Int = 3 }\ntrait C extends A { override def f: Int = 4 ; def g: Int }\ntrait D extends B with C { def h: Int }\n
Run Code Online (Sandbox Code Playgroud)\n

因此至少它看起来确实是一种特定的行为。

\n

基于fr_andres 的回答学习 Scala,第 9 章:对象、案例类和特征

\n
\n

当编译为 .class 二进制文件时,扩展类 A 和特征 B 和 C 的类实际上扩展了一个类,该类扩展了另一个类,该类又扩展了另一个类。

\n
\n

由于线性化意味着有效

\n
LoggerA (has concrete log)\n  ^\n  |\nLoggerB (also has concrete log)\n  ^\n  |\nLogged3\n
Run Code Online (Sandbox Code Playgroud)\n

并且override在覆盖具体实现时是必要的。

\n