如何防止超类调用overriden子类方法?

时间:2017-04-03 02:16:30

标签: java inheritance polymorphism override

我刚遇到这个问题,这让我感到意外。

超类:

public class Foo {

    @Override
    public String toString(){
        return String.format("Result = %s", calculate());
    }
    public double calculate(){
        return 1;
    }
}

子类:

public class Bar extends Foo {
    @Override
    public String toString(){
        return String.format("%s", super.toString());
    }
    @Override
    public double calculate(){
        return 123.456;
    }
}

驱动器:

public static void main(String[] args) {
    System.out.println(new Bar().toString());
}

此方案中我希望的输出是1 我得到的输出是123.456

如何阻止Foo toString()致电Bar calculate()

2 个答案:

答案 0 :(得分:6)

如果您不想让子类覆盖calculate,请将其标记为final

public final double calculate() {
    ...
}

如果您想让它们覆盖calculate,但您不想在此特定位置使用覆盖,请将calculate的实现放在私有方法中并使用私有版本:

public double calculate() {
    return _calculate();
}
private double _calculate() {
    return 1.0;
}
@Override
public String toString(){
    return String.format("Result = %s", _calculate());
}

答案 1 :(得分:5)

您无法直接执行此操作 - 您已覆盖calculate()并且由于您拥有Bar个对象,因此在使用Bar.calculate()时将调用它calculate() > 1 。如果是其他任何方式,那么制作合理的OoO设计会非常困惑和困难!

如果您真的想要所描述的行为,通常的解决方案就是让Foo.toString()调用一个不可覆盖的(例如,privatefinal)辅助方法来实现逻辑你在Foo.calculate()中有的。然后,您可以确信toString()始终以相同的方式运行,即使Foo被覆盖 2 。然后,你可以通过调用这个帮助器方法来实现Foo.calculate(),取悦DRY诸神。

当然,您可能会问自己,您的班级设计是否有问题。上面建议的更改意味着您遇到Foo.calculate()即使在toString()个对象上Bar来电,{em>直接调用calculate()的异常情况将导致Bar行为。因此,您的toString()输出将与调用calculate()的任何人看到的内容不一致。这很少是你想要的。

1 除了Bar 之内的,可以使用calculate()显式调用超类super.calculate()方法。这对你没有帮助,因为你想要做的是,在超类中,阻止对calculate()的虚拟呼叫去其他地方。

2 当然,如果某人覆盖toString(),那么所有投注都将被取消。如果你想避免这种情况,你总是可以final