首页 文章

如何强制子类调用抽象实现的方法

提问于
浏览
6

基本上,我想做的是 force 子类来调用抽象超类方法(在子类中实现),所以每次创建新的子类时我都不必显式地写它 .

我在超类的构造函数中写了一次,因为我希望它强制它用于每个实现 .

public abstract class SupahClass {
    public SupahClass() {
        doStuff(); // It IS executed when the subclass constructor is called
        init(); // NOT executed, even though it's implemented
    }

    private void doStuff() { ... }        

    protected abstract void init();
}

public class SomeSubClass extends SupahClass {

    // The problem lies HERE: this is executed AFTER init() ... so it gets NULL again
    private TextBox myTextBox = null;

    public SomeSubClass() {
        super(); // invokes the super constructor, so init() should be called
        // I could call init(); here EACH time i create a new subclass... but no :)
    }

    @Override
    public void init() {
        this.myTextBox = new TextBox(); // Executed BEFORE its declared as null above
    }
}

当然,超类不能真正调用它,因为它是一个抽象(如此未定义)的方法,但它是一个ABSTRACT类,所以它不能实例化,它必须将任务委托给它的子类,所以为什么它们不能调用抽象但现在实施方法?

EDIT 请参阅子类属性 myTextBoxinit() 实现

你认为我应该采取哪种方法?删除属性声明中的 = null (duhhh)

或删除超类中的 init() 并在子类构造函数中显式调用它(这是我想要避免的,因为我必须在100%的时间内写它..)

4 回答

  • 2

    您可以通过将声明更改为:

    private TextBox myTextBox;
    

    赋值为null没有任何用处 . 如果没有超类,它将什么也不做,因为无论如何字段都被初始化为null . 由于有一个超类,它起到了脚的枪声 . 所以,摆脱它 .

  • 8

    我无法重现这一点 . 假设没有先抛出异常,将调用 init() . 简短而完整的例子:

    abstract class Superclass {
       public Superclass() {
           init();
       }
    
       protected abstract void init();
    }
    
    class Subclass extends Superclass {
       public Subclass() {
           super();
       }
    
       @Override
       public void init() {
           System.out.println("Subclass.init called");
       }
    }
    
    public class Test {    
        public static void main(String[] args) throws Exception {
            new Subclass();
        }
    }
    

    这会按预期打印“Subclass.init” . 我怀疑你没有向我们展示的代码中有其他错误 .

    请注意,在构造函数中调用虚方法是一项有风险的业务 - 子类尚未初始化 - 例如,所有变量都将具有其默认值 . 这通常是一种需要避免的模式 .

  • 0

    抽象类 can 调用抽象方法 .

  • 2

    您是否使用调试器来了解代码的作用?

    构造的顺序是1.基类的构造函数2.初始化派生类的所有成员3.派生类的构造函数 .

    在您的情况下,步骤1初始化成员(在派生类的init中 - 通过多态调用调用),但步骤2将其设置为null .

相关问题