抽象静态成员初始化

时间:2012-06-07 18:32:07

标签: java abstract-class

我希望派生类有自己的记录器,但看起来我不能:

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但不要Cnew C1()会产生此输出:

C1: C
C1: C1

(第一行来自C构造函数,第二行来自C1构造函数)。相反,我在nullPointerException中获得C,因为lnull

我无法在l中将abstract变为C,我也不想在那里初始化它,因为那时输出将是

C: C
C1: C1

我有什么选择?

谢谢!

2 个答案:

答案 0 :(得分:6)

解决方案1(经典)

一种可能的方法是在抽象类中使用抽象的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
  }
}

您还可以在抽象类中提供默认实现,以强制子实现覆盖。您可以使抽象类的使用者更容易(开发具体的类),但是您不会强制执行该方法的细粒度。

解决方案2(啰嗦......)

另一个更暴力的解决方案是在抽象类中使用getMagicLogger()方法,它将在运行时确定当前实例的具体类型,以返回新的记录器实例,每次或延迟加载它并将其存储在一个字段中。

抽象类通过这种方式处理所有这些并且对消费者来说非常容易,但这是一件很疯狂的事情。 AND,这意味着Logger显然不是静态字段。

答案 1 :(得分:4)

静态成员没有属性覆盖,l中的C记录器是C中声明的记录器(为空),不是来自C1子类。