考虑这个MWE:
public class Base {
public int myRecursiveAlgo(int a) {
if (a == 0) { return 0; }
return a + myRecursiveAlgo(a - 1);
}
}
public class Child extends Base {
public int myRecursiveAlgo(int a) {
return super.myRecursiveAlgo(a) + 1; // modification
}
}
现在,你看,Child::myRecursiveCall()
想要将最终结果调整1。但是,Base::myRecursiveAlgo()
现在被递归调用分派给Child::myRecursiveAlgo()
的事实打破了。我如何从基类显式地调用Base::myRecursiveAlgo()
?
在c++中,您可以执行return a + Base::myRecursiveAlgo(a - 1);
来防止调用该方法的子类重写变体。
你不能。没有办法。
因此,你编写的任何调用你自己的方法的代码都需要做这些事情之一,否则你的代码就会以一种尚未测试的方式被破坏(即等待发生的灾难,非常糟糕):
-
你要调用的方法需要是
private
,或者是包私有的,并且有充分的文档记录,以便所有在同一包内操作的人都知道它所需的属性。 -
或者,方法必须为
final
,或者你的类需要有效地为final
(如果它是非final的,但所有构造函数都是private
,它实际上是final的-任何重载只能通过在同一源文件中写入子/兄弟来发生,并且可能任何人都知道这些条件,或者至少负责遵守这些条件)。 -
或者,您的方法将不依赖于它所拥有的任何属性,或者,它所依赖的属性至少是文档化的,并且有一个警告。
-
或者,让您的可重写方法是一个单行程序,将工作分配给不可重写的方法(例如私有方法和/或最终方法)。在需要将属性专门锁定到基本实现的地方,调用helper。当然,这本身就令人困惑:如果有人决定重写该方法,那么奇怪的是,在某些情况下,他们的重写根本没有被调用。
第三种(记录它,并祈祷)确实存在-例如,您可以自由地为某些类编写不一致的equals/hashCode算法,然后使用该类的实例作为HashMap中的键,但结果将是奇怪的,Map的各种方法完全撒谎,并且在意外时间发生奇怪的异常。据推测,这是在决定不阅读equals/hashCode的合同要求的发光灯上。
如果你有必要,你也可以做同样的事情。