gpt4 book ai didi

java - 在抽象类的构造函数中使用抽象 init() 函数

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:53:54 25 4
gpt4 key购买 nike

我有这样的东西:

    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();

如您所见,父类(super class)的 init 方法是抽象的,在创建对象后由构造函数自动调用。

我很好奇,当我需要创建一些结构不会及时更改的此类对象时,我是否会遇到这样的代码问题。

有什么更好的方法吗?它在 Java 中工作,但它会在 C++ 和可能的 ActionScript 中工作吗?

谢谢你的回答。

最佳答案

不要从构造函数中调用可覆盖的方法。

引自 Effective 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还没有完成对final int x的初始化,并且该方法得到了错误的值。这几乎肯定会导致错误和错误。

相关问题

另见

关于java - 在抽象类的构造函数中使用抽象 init() 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3342784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com