如何用 `super` 修复这个特性?

How to fix this traits with `super`?

Scala 代码:

trait Logger {
  def log(msg: String)
}

trait TimeLogger extends Logger {
  def log(msg: String) = super.log(new Date + ": " + msg)
}

class MyApp extends TimeLogger {
  override def log(msg: String): Unit = println(msg)

  log("Hello")
}

new MyApp()

我编译的时候报错:

Error:(12, 34) method log in trait Logger is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'
    def log(msg: String) = super.log(new Date + ": " + msg)
                                 ^

我不太明白,为什么要声明一个abstractoverridelog方法?如何解决?

据我所知,您的 Logger 特征中没有 log 的实现。通过从 TimeLogger 调用 super.log,您正在调用一个未实现的方法。

您似乎正试图重写一个方法,但并未完全定义它。你不能从它自己的实现中调用你正在覆盖的方法(除非你想要递归)。而不是调用未实现的 super.log,我相信您实际上想调用子 class 的日志记录的 实现 。你当然不能对两者使用相同的函数原型。

也许您可以按以下方式定义 TimeLoggerMyApp

trait TimeLogger extends Logger {
  def logImpl(msg: String)
  def log(msg: String) = logImpl(new Date + ": " + msg)
}

class MyApp extends TimeLogger {
  override def logImpl(msg: String): Unit = println(msg)

  log("Hello")
}

Scala 特征,以您使用的方式 Log 本质上是接口,即行为规范。所以你的类型

trait Logger {
  def log(msg: String)
}

trait TimeLogger extends Logger {
  def log(msg: String) = super.log(new Date + ": " + msg)
}

是说 Logger 的实例将提供它自己的 log(msg: String) 实现。由于'log'没有在Logger中实现,因此无法用super.调用它。

但是,如果您要从 MyApp 调用 super.log,那么它将执行 TimeLogger.log 调用。

如果我错了请纠正我,但我认为您正试图用时间戳装饰任何记录器实现的日志函数。

因此,您想使用 TimeLogger 特性作为 装饰器 用于 Logger 实现,委托说 printlnLog4j,甚至 android.Log.

有两种方法(我能想到)可以实现这样的目标:

1)

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

class PrintStreamLogger extends Logger {
  def log(msg: String): Unit = println(msg)
}

abstract class TimeLogger(loggerImpl: Logger) extends Logger {
  def log(msg: String): Unit = loggerImpl.log(new Date + ": " + msg)
}

class MyApp extends TimeLogger(new PrintStreamLogger) {
  log("Hello")
}

2)

trait Logger {
  def log(msg: String): Unit = logImpl(msg)

  protected def logImpl(msg: String): Unit
}

trait TimeLogger {
  loggerImpl: Logger =>
  override def log(msg: String): Unit =
    loggerImpl.logImpl(s"${new Date}: $msg")
}

class MyApp extends Logger with TimeLogger {
  protected def logImpl(msg: String): Unit = println(msg)
  log("Hello")
}

我有另一种方法来修复它,方法是创建一个扩展 Logger 的特征 PrintLogger,然后将它们混合在 MyApp:

trait Logger {
  def log(msg: String)
}

trait PrintLogger extends Logger {
  override def log(msg: String): Unit = println(msg)
}

trait TimeLogger extends Logger {
  abstract override def log(msg: String) = super.log(new Date + ": " + msg)
}

class MyApp extends PrintLogger with TimeLogger {
  log("Hello")
}

new MyApp()