Ant*_*tte 2 java polymorphism inheritance overriding
我刚刚遇到这个问题,它让我感到意外.
超一流:
public class Foo {
@Override
public String toString(){
return String.format("Result = %s", calculate());
}
public double calculate(){
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
子类:
public class Bar extends Foo {
@Override
public String toString(){
return String.format("%s", super.toString());
}
@Override
public double calculate(){
return 123.456;
}
}
Run Code Online (Sandbox Code Playgroud)
司机:
public static void main(String[] args) {
System.out.println(new Bar().toString());
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下我想要1
的输出是我得到的输出123.456
如何阻止Foo toString()调用Bar calculate()?
如果您不想让子类重写calculate,请标记它final:
public final double calculate() {
...
}
Run Code Online (Sandbox Code Playgroud)
如果您想让它们覆盖calculate,但您不想在此特定位置使用覆盖,请将实现calculate放在私有方法中并使用私有版本:
public double calculate() {
return _calculate();
}
private double _calculate() {
return 1.0;
}
@Override
public String toString(){
return String.format("Result = %s", _calculate());
}
Run Code Online (Sandbox Code Playgroud)
你不能直接这样做 - 你已经被覆盖了calculate(),因为你有一个Bar对象,所以Bar.calculate()在calculate()使用时它总是会被调用1.如果是其他任何方式,那么制作合理的OoO设计会非常困惑和困难!
如果你真的想要所描述的行为,通常的解决方案就是Foo.toString()调用一个不可覆盖的(例如,private或final)辅助方法来实现你所拥有的逻辑Foo.calculate().然后你就可以放心toString(),即使Foo被覆盖也总是以同样的方式行事2.然后,你可以Foo.calculate()通过调用这个辅助方法来实现,取悦DRY神.
当然,您可能会问自己,您的班级设计是否有问题.上面建议的更改意味着你有一个不寻常的情况,即使在对象上Foo.calculate()也用于toString()调用Bar,但直接调用calculate()将导致Bar行为.所以你的toString()输出将与任何打电话的人calculate()都看到不一致.这很少是你想要的.
1除了可以在内部Bar显式调用超类calculate()方法之外super.calculate().这对你没有帮助,因为你想要做的是,在超类中,阻止虚拟调用calculate()进入其他任何地方.
2当然,如果有人覆盖,toString()那么所有投注都将被取消.final如果你想避免这种情况,你总是可以做到.