.Net 填坑 接口、父类、子类同名方法的调用
先看代码
1.类与接口定义
class B : IDisposable, Test
{
public void Dispose()
{
Console.WriteLine("B Dispose");
}
public virtual void Test()
{
Console.WriteLine("B Test");
}
}
interface Test
{
void Test();
}
class C : B, Test
{
public new void Test()
{
Console.WriteLine("C Test");
}
}
2.调用方法
static void Main(string[] args)
{
Test c = new C();
c.Test();
c = new B();
c.Test();
B b = new C();
b.Test();
Console.ReadLine();
}
输出如下:
C Test
B Test
B Test
1.其中第一输出,表示用接口类变量来调用方法时,(类似虚方法调用),会找到变量对应的实际实例(此例子中是类型C的实例对象c),找到实例的类型对象(C类型)的Test方法。
2.第二个输出,同一个原则,实际类型是B类型,所以输出B
3.按照虚方法定义,也应该找到对应实际类型的Test方法来输出,但是输出的是B。原因在于C方法中的New关键字,表示是C类型独有的新的方法,而不是真正的C中的重写父类B中的方法,所以流程是:先找到C类型对象,查找虚方法Test,结果是没找到,然后再去B类中找,找到了,调用B类中的方法。
对应的I代码:
IL_0007: ldloc.0 // c
IL_0008: callvirt instance void Program/Test::Test()
IL_000d: nop
IL_0014: ldloc.0 // c
IL_0015: callvirt instance void Program/Test::Test()
IL_001a: nop
IL_0021: ldloc.1 // b
IL_0022: callvirt instance void Program/B::Test()
IL_0027: nop
可以看到,接口变量调用方法也是虚方法调用的方式
1.将C中的New 改为override后
结果:
C Test
B Test
C Test
第3个流程发生变化,此时C中Test认为是复写了父类B中的虚方法,所以按虚方法的流程,找到实际对象中C的方法进行了调用。
2.去掉C中继承的Test接口
class C : B
{
public override void Test()
{
Console.WriteLine("C Test");
}
}
打印结果:与上面相同,都是走的虚方法调用
3.去掉C中的Test接口,同时修改C中方法为New
class C : B
{
public new void Test()
{
Console.WriteLine("C Test");
}
}
结果:
B Test
B Test
B Test
此时C中的Test方法,认为是新的只属于C的方法。
1.第一个变为打印B,因为接口走的虚方法调用的原理,去找实际类型C中有没有覆盖的Test方法,没找到(因为New关键字表示C独有的新的方法),然后找到父类B中的虚方法去调用。
2.第2个,找到实例对象B的虚方法,找到了,直接调用
3.第3个,还是B,因为用虚方法调用,去找C中的复写Test虚方法,没找到,从而去找父类B中的,流程与1相同
总结
方法调用,要看调用方法的方式,实例方法与虚方法。
实例方法,直接按变量类型,去找到对应的方法直接调用
实例虚方法,找到变量实际的存储类型,去一层层找到有无复写的虚方法
注意:new与override关键字的区别,特别是new关键字,可以当做是独立的属于类型自身的方法。
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » .Net 填坑 接口、父类、子类同名方法的调用
发表评论 取消回复