我希望派生类有自己的记录器,但看起来我不能:
abstract class C {
final protected static Logger l;
C (...) {
l.emit("C");
}
}
class C1 extends C {
final protected static Logger l = new Logger("C1");
C1 (...) {
super(...);
l.emit("C1");
}
}
我希望Logger
中有C1
但不要C
,new C1()
会产生此输出:
C1: C
C1: C1
(第一行来自C
构造函数,第二行来自C1
构造函数)。相反,我在nullPointerException
中获得C
,因为l
有null
。
我无法在l
中将abstract
变为C
,我也不想在那里初始化它,因为那时输出将是
C: C
C1: C1
我有什么选择?
谢谢!
答案 0 :(得分:6)
一种可能的方法是在抽象类中使用抽象的getLogger()
方法,以便派生类被强制提供自己的记录器。
public class AbstractClass {
abstract Logger getLogger();
public void someMethodInAbstractClass() {
getLogger().debug("something"); // will output using provided child logger
}
}
public class ConcreteClass extends AbstractClass {
private static final Logger LOGGER = Logger.getLogger(ConcreteClass.class);
@Override
Logger getLogger() {
return (LOGGER);
}
public void someMethod() {
getLogger().debug("something"); // will output using local logger
}
}
您还可以在抽象类中提供默认实现,以强制子实现覆盖。您可以使抽象类的使用者更容易(开发具体的类),但是您不会强制执行该方法的细粒度。
另一个更暴力的解决方案是在抽象类中使用getMagicLogger()
方法,它将在运行时确定当前实例的具体类型,以返回新的记录器实例,每次或延迟加载它并将其存储在一个字段中。
抽象类通过这种方式处理所有这些并且对消费者来说非常容易,但这是一件很疯狂的事情。 AND,这意味着Logger显然不是静态字段。
答案 1 :(得分:4)
静态成员没有属性覆盖,l
中的C
记录器是C
中声明的记录器(为空),不是来自C1
子类。