我有这样的事情:
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中使用吗?
谢谢你的答案.
不要从构造函数中发现过多的方法.
来自Effective Java 2nd Edition,第17项:设计和继承文档的引用,或者禁止它:
为了允许继承,类必须遵守一些限制.构造函数不得直接或间接调用可覆盖的方法.如果违反此规则,将导致程序失败.超类构造函数在子类构造函数之前运行,因此在子类构造函数运行之前将调用子类中的重写方法.如果重写方法依赖于子类构造函数执行的任何初始化,则该方法将不会按预期运行.
这是一个例子来说明:
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
尚未完成初始化final int x
,并且该方法获取错误的值.这几乎肯定会导致错误和错误.
从父类构造函数调用重写方法
当Base类构造函数在Java中调用重写方法时,Derived类对象的状态
FindBugs - 从超类的构造函数调用的字段方法的未初始化读取