我有一个抽象类(Java库),该类带有构造函数参数,并且有一个我要装饰的名为HttpRequest
的方法:
execute
我有Scala类,当前继承了前一个:
public abstract class Task {
private final String name;
protected Task(String name) {
this.name = name;
}
public abstract void execute(String str) throws Exception
}
是否可以为Task类编写这样的装饰器:
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")
}
然后使用它来记录错误?
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
修饰符不会编译。什么是实现此日志记录解决方案的正确方法?也许除了可堆叠特征以外还有其他选择吗?
答案 0 :(得分:3)
当前,装饰器的重写方法将被忽略(它会编译,但不会执行)
它没有执行,因为它在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