Answers:
是的,他们有。它被称为OO的斯堪的纳维亚模型,例如在Simula中使用(另一种广泛使用的OO模型现在被认为是美国模型)。在斯堪的纳维亚模型中,您不是在压倒一切,而是在提供子行为。
在超类的方法foo中:
some-code-before
INNER // this is the actual Simula keyword
some-code-after
在子类的方法foo中:
some-code-in-subclass
如果调用父类的实例foo方法,只有some-code-before
和some-code-after
情况(INNER
什么都不做),但如果调用子类实例FOO,它some-code-before
,some-code-in-subclass
然后some-code-after
。
我所知道的语言都没有强制调用重写方法。实际上,某些语言允许使用不可替代的替代方法(例如new
在C#中使用关键字)。但是,有两种方法可以解决此问题。
第一种是创建一个不可覆盖的方法(例如,virtual
在C#中缺少关键字或final
在Java 中具有关键字的方法),该方法调用无法从类外部调用的可覆盖方法(例如,protected
在C#,Java或C ++中)。
class C
A
statement1
F
statement3
protected virtual F
statement2
和
class D inherits C
protected override F
statement4
C.F()
类覆盖C
可以随意覆盖F
和修改其行为,但是来自类外部的调用者只能通过访问A
。
编辑:正如其他人指出的那样,这称为Template方法模式。
第二种方法是使用强制执行基类中指定的前提条件和后置条件的语言,例如带有代码协定的Eiffel或C#。它不会强制调用基类,但是可以强制重写方法执行相同的语句。如果语言允许继承方面,则使用方面也可能会有所帮助。
private
在C ++中被覆盖:) Herb Sutter 在此详细说明。
这并不是语言的真正组成部分,但是Java的FindBugs静态代码分析器具有注释OverrideMustInvoke
,开发人员可以将其添加到方法中,并且如果发现未调用超级实现的重写方法,这将导致FindBugs显示错误。 。它甚至允许在覆盖方法中指定调用必须是第一个还是最后一个。
要求调用超类方法是反模式。如果在编译时未强制执行,则容易出错,这就是为什么您要寻找一种语言结构来对其进行检查的原因。
所有OO语言都支持一种方法:模板方法pattern。在这里,使超类方法不可重写,并在其中调用可重写方法。然后,子类可以重写此方法以添加功能:
class super {
public final void doSomething() {
doSpecialthing();
doMore();
}
public void doSpecialthing() {
}
}
根据对重写方法的调用位置,它甚至还可以确定执行顺序,对于普通的super调用,子类实现者可以随意执行。
我能想到的最接近的模式是自我订阅的事件。这有点麻烦,对于编码人员来说一点也不直观,但是可以达到目标。
class C
{
public void F()
{
...
OnF()
}
protected event OnF
}
class D : C
{
public D()
{
base.OnF += this.F
}
private void F
{
...
}
}
从理论上讲,这虽然不是一个坏主意,但它的负面影响确实是在实施时限制了我的选择D
。例如,如果(出于某些不可思议的原因),F
从其他方法调用超类实现会更方便:
class D inherits C
override F
statement1
statement2
G()
G
statement3
C.F()
statement4
在您的情况下,我想象编译器会标记F
in 的实现D
,即使它(间接)调用C.F()
。
基本上,您所描述的是一种可能的机制,可以帮助编译器识别何时C
违反了从其继承的类的协定。我的观点是,虽然这是一个伟大的事情,它不应以限制的代价如何,我可以实现我的子类。