我刚遇到这个问题,这让我感到意外。
超类:
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()
?
答案 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()
调用一个不可覆盖的(例如,private
或final
)辅助方法来实现逻辑你在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
。