繁体   English   中英

在构造函数中使用重写方法的替代方法,Java

[英]Alternatives to using overridden methods in constructors, Java

在我编写的Java项目中,我最终使用了在构造函数中重写的方法。 就像是:

class SuperClass {
    SuperClass() {
        intialise();
    }

    protected void initialise() {
        //Do some stuff common to all subclasses
        methodA();
        methodB();
    }

    protected abstract void methodA();

    protected abstract void methodB();
}

class SubClass1() {
    SubClass() {
        super();
    }
    protected void methodA() { //Do something }
    protected void methodB() { //Do something }

}

class SubClass2() {
    SubClass() {
        super();
    }
    protected void methodA() { //Do something else }
    protected void methodB() { //Do something else}

}

我现在意识到,虽然在我的情况下它工作正常,但是有点危险,因为SubClass方法在一个目前只被构造为SuperClass对象的对象上调用(当扩展SuperClass的新类被添加时,可能会忽略这一点)未来)。 由于对象的创建方式不同,它在c ++中也不起作用。

我能想到的唯一方法就是将initialise方法调用向下移动到具体的类构造函数:

   class SuperClass {
    SuperClass() {            
    }

    protected void initialise() {
        methodA();
        methodB();
    }

    protected abstract void methodA();

    protected abstract void methodB();
}

class SubClass1() {
    SubClass() {
        super();
        initialise();
    }
    protected void methodA() { //Do something }
    protected void methodB() { //Do something }

}...

这是解决这个问题的常用方法吗? 扩展SuperClass的所有其他类需要记住调用initialise()似乎是一种耻辱(并且容易忘记)。

我还发现自己在更复杂的情境中做了类似的事情,它在构造函数中使用了Factory方法,在子类中重写它以决定实现哪个具体类。 我能想到的唯一另一种方法是将这种设计模式保持原样,或许可以构建一个两阶段的过程; 即用最小的构造,然后调用第二种方法来完成工作。

需要初始化的对象实际上需要通过工厂方法创建。 你确实提到了一个工厂,但是从构造函数中调用,所以这听起来也不像是简单的方法。 如果你只是在基类中有一个工厂,公共不可见的构造函数,以及一个决定返回哪个具体类的机制,那么工厂将很容易地执行初始化策略。

这实际上不是一个好主意,因为当调用其methodA()和methodB()时,您的子类将无法正确构造。 对于扩展课程的人来说,这将是非常混乱的。 建议您使用抽象的init() ,如dlev在他/她的评论中所建议的那样。

我想知道你是否让事情变得比他们需要的更复杂。

在您的示例中,methodA的每个实现所完成的工作可以移动到执行该实现的类的构造函数中。 因此,不要使用SubClass :: methodA,只需将逻辑移动到SubClass构造函数中。

如果你这样做,你可以获得清晰,代价是可能难以理解对各种初始化位执行顺序的控制。

Bruce Eckel在他的“Thinking in Java”中提出的建议是使你的methodA()和类SuperClass的方法B()最终或私有(隐式最终),因此它们可以从超类构造函数访问,尽管没有派生类会有访问这些方法,因此,不会有任何危险的覆盖 - 任何派生类中声明的类似签名的任何方法都只是新方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM