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

dom*_*ri7 6 java inheritance implementation abstract

基本上,我想要做的是强制子类调用抽象超类方法(在子类中实现),因此每次创建新子类时我都不必显式地编写它.

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

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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Jon*_*eet 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Tom*_*son 2

您可以通过将声明更改为来解决此问题:

private TextBox myTextBox;
Run Code Online (Sandbox Code Playgroud)

分配给 null 没有任何用处。如果没有超类,它不会执行任何操作,因为无论如何字段都会初始化为 null。既然有超类,那它的作用就相当于是对脚上的一枪。所以,摆脱它吧。