这里需要注意的一件事是,每次都会调用覆盖的版本。将替代更改为:
public override void MyMethod(string s = "bbb"){ Console.Write("derived: "); base.MyMethod(s);}输出为:
derived: bbbderived: aaa
类中的方法可以执行以下一项或多项操作:
- 它定义了其他代码调用的接口。
- 它定义了一个在调用时执行的实现。
它可能不会两者都做,因为抽象方法只会做前者。
在
BBB调用
MyMethod()调用方法 定义 在
AAA。
由于中存在覆盖
BBB,因此调用该方法将导致实现
BBB被调用。
现在,中的定义
AAA将两件事告知调用代码(嗯,还有一些无关紧要的地方)。
- 签名
void MyMethod(string)
。 - (对于支持该语言的语言)单个参数的默认值为
"aaa"
,因此,MyMethod()
如果在找不到该方法匹配的形式的形式的代码时MyMethod()
,可以用对MyMethod(“ aaa”)的调用来替换它。
因此,这就是调用的
BBB作用:编译器看到对的调用
MyMethod(),未找到方法,
MyMethod()但确实找到了方法
MyMethod(string)。它还可以看到在定义它的地方有一个默认值“
aaa”,因此在编译时它将其更改为对的调用
MyMethod("aaa")。从内部
BBB,即使在中被覆盖,也
AAA被认为
AAA是定义方法的地方
BBB,以便 可以 覆盖它们。
在运行时,
MyMethod(string)使用参数“ aaa”调用。因为存在一个覆盖的形式,所以该形式被调用,但是不使用“
bbb”来调用它,因为该值与运行时实现无关,而与编译时定义无关。
添加
this.更改将检查哪个定义,从而更改调用中使用的参数。
编辑:为什么这对我来说似乎更直观。
就个人而言,由于我所说的是直观的东西,因此只能是个人的,我发现它更直观,原因如下:
如果我正在编码,
BBB那么无论是调用还是覆盖
MyMethod(string),我都认为这是“正在做的
AAA事情”,这是
BBB在“正在做的
AAA事情”
上做的事情,但实际上
AAA都是在做事情。因此,无论是调用还是覆盖,我都将意识到它就是
AAA定义的事实
MyMethod(string)。
如果我要调用使用过的代码
BBB,我会想到“使用
BBB东西”。我可能不太了解最初是在中定义的
AAA,因此我可能会认为这只是实现细节(如果我也没有使用
AAA附近的接口)。
编译器的行为符合我的直觉,这就是为什么当初读这个问题时,我觉得Mono有一个错误。经考虑,我看不到任何一个如何比另一个更好地实现指定的行为。
尽管如此,尽管如此,在保持个人水平的同时,我绝不会将可选参数与抽象,虚拟或重写方法一起使用,并且如果要覆盖其他人使用的参数,我会匹配它们。



