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

时间:2015-08-04 14:23:47

标签: scala super traits

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)
                                 ^

我不太明白,我为什么要宣布abstractoverride log方法?如何解决?

4 个答案:

答案 0 :(得分:2)

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

Log

表示trait Logger { def log(msg: String) } trait TimeLogger extends Logger { def log(msg: String) = super.log(new Date + ": " + msg) } 的实例会提供自己的Logger实现。由于log(msg: String)中未实现“日志”,因此无法使用Logger调用它。

但是,如果您要从super.致电super.log,那么它会进行MyApp来电。

答案 1 :(得分:1)

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

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

也许您可以通过以下方式定义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")
}

答案 2 :(得分:1)

如果我错了,请纠正我,但我认为您正在尝试使用时间戳来装饰任何记录器实现的日志功能。

因此,您希望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")
}

答案 3 :(得分:0)

我还有另一种方法可以通过创建一个特征PrintLogger来扩展Logger来修复它,然后在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()