public abstract class Menu { public Menu() { init(); } protected abstract void init(); protected void addMenuItem(MenuItem menuItem) { // some code... } } public class ConcreteMenu extends Menu { protected void init() { addMenuItem(new MenuItem("ITEM1")); addMenuItem(new MenuItem("ITEM2")); // .... } } //Somewhere in code Menu menu1 = new ConcreteMenu();
正如你可以看到超类的init方法是抽象的,并且在创建对象之后被构造函数自动调用.
我很好奇,如果我可以遇到一些这样的代码的问题,当我需要创建一些这样的对象,其结构不会及时更改.
会有更好的办法吗?它在Java中工作,但它可以在C和ActionScript中工作吗?
谢谢你的答案.
解决方法
有效的Java第2版,第17项:继承的设计和文档的引用,否则禁止它:
There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods,directly or indirectly. If you violate this rule,program failure will result. The superclass constructor runs before the subclass constructor,so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor,the method will not behave as expected.
下面是一个例子来说明:
public class ConstructorCallsOverride { public static void main(String[] args) { abstract class Base { Base() { overrideMe(); } abstract void overrideMe(); } class Child extends Base { final int x; Child(int x) { this.x = x; } @Override void overrideMe() { System.out.println(x); } } new Child(42); // prints "0" } }
在这里,当Base构造函数调用overrideMe时,Child还没有完成初始化最终的int x,并且该方法获得错误的值.这几乎肯定会导致错误和错误.
相关问题
> Calling an Overridden Method from a Parent-Class Constructor
> State of Derived class object when Base class constructor calls overridden method in Java
也可以看看
> FindBugs – Uninitialized read of field method called from constructor of superclass