我有一个抽象类(Java库),它接受构造函数参数,并有一个我想要装饰的名为execute
的方法:
public abstract class Task {
private final String name;
protected Task(String name) {
this.name = name;
}
public abstract void execute(String str) throws Exception
}
我有Scala类,目前继承前一个:
class FooTask extends Task("fooTask") {
override def execute(str: String): Unit = println(str + "foo")
}
class BarTask extends Task("barTask") {
override def execute(str: Strin): Unit = println(str + "bar")
}
是否可以像这样为Task类编写一个装饰器:
trait TaskWithErrorLogging { self: Task =>
override def execute(str: String): Unit =
Try(self.execute(str)) match {
case Failure(exception) =>
println("LOGGED " + exception)
throw exception;
case _ =>
}
}
然后使用它来记录错误?
class BarTask extends Task("barTask") with TaskWithErrorLogging {
override def execute(str: String): Unit = println(str + "bar") // Error should be logged
}
这些任务由框架的注入器自动实例化,因此无法编写new FooTask with TaskWithErrorLogging
目前,decorator的重写方法被忽略(它编译,但不执行)。将abstract
修饰符添加到装饰器中的方法不会编译。实施此日志记录解决方案的正确方法是什么?除了可堆叠的特性外,还有其他选择吗?
目前,decorator的重写方法被忽略(它编译,但不执行)
它不会执行,因为它在BarTask
中被覆盖。如果它确实执行,它有无限递归:self.execute(str)
将调用相同的方法。
最简单的方法是
trait TaskWithErrorLogging extends Task {
override def execute(str: String): Unit =
Try(doExecute(str)) match {
case Failure(exception) =>
println("LOGGED " + exception)
throw exception;
case _ =>
}
def doExecute(str: String): Unit
}
class BarTask extends Task("barTask") with TaskWithErrorLogging {
override def doExecute(str: String): Unit = println(str + "bar")
}
或者如果你真的想要使用可堆叠的装饰器,那么TaskWithErrorLogging
仍然需要在它装饰的方法之后混合,例如
trait TaskWithErrorLogging extends Task {
abstract override def execute(str: String): Unit =
Try(super.execute(str)) match { // note super, not self!
case Failure(exception) =>
println("LOGGED " + exception)
throw exception;
case _ =>
}
}
class BarTask0 extends Task("barTask") {
override def execute(str: String): Unit = println(str + "bar")
}
class BarTask extends BarTask0 with TaskWithErrorLogging