using System;
namespace 重写父类方法
{
class Father
{
public void F_Out()
{
this.OutPut();
}
public void OutPut()
{
Console.WriteLine("调用父类OutPut方法");
}
}
class Sub : Father
{
public new void OutPut()
{
Console.WriteLine("调用子类OutPut方法");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Sub sub = new Sub();
sub.F_Out();
}
}
}
上面输出调用父类OutPut方法
没明白为什么隐藏父类的OutPut方法会造成这样的结果, this.OutPut();应该就是是sub.OutPut()所以调用的应该是子类的OutPut方法啊,然后使用重写的方法正确了。没明白怎么回事,不管怎么样,this.OutPut就应该是sub.OutPut?
using System;
namespace 重写父类方法
{
class Father
{
public void F_Out()
{
this.OutPut();
}
public virtual void OutPut()
{
Console.WriteLine("调用父类OutPut方法");
}
}
class Sub : Father
{
public override void OutPut()
{
Console.WriteLine("调用子类OutPut方法");
}
}
class Program
{
static void Main(string[] args)
{
Sub sub = new Sub();
sub.F_Out();
}
}
}
下面这个输出调用子类OutPut方法。
真是个很好的问题以及示例(起码对我个人而言是这样的)。
以下是我的理解以及参考。
new
微软文档 new 修饰符 中有这么一句话:
我的理解是,这个隐藏仅仅只是针对派生类而言的,并没有对基类造成任何影响。
Override
微软文档 virtual 关键字 中有这么一句话:
我的理解是:使用了 virtual 关键字的成员,在运行时,才会确定其当前所属的对象的具体类型。
此时,通过 override 的示例代码中的
new Sub()
执行F_Out()
,程序会确定对象实际类型是Sub
,所以,会执行Sub
的OutPut
。在网上一些其他资料中,大致搜集到这么一个结论:
从编译角度讲:
普通成员在编译时,其引用的相对地址就已经被程序确定好了。因此程序运行时,将会直接根据该地址调用该成员。即:在编译时,new 的示例代码中的
Father
的F_Out
方法中,就已经把OutPut
方法的引用确定好了(也就是Father
的OutPut
方法的引用)。而虚成员在编译时,并没有将其引用固定写在程序的执行文件。因此程序运行时,才会检查当前对象(也就是类的实例)到底是什么类型。当该对象调用虚成员时,会发现该成员是虚成员,然后就会查找它的重写成员。从该实例的具体类型开始,一层一层地向上(即其父类)查找,找到后就会执行。即:override 的示例代码中的
Sub
实例化后,调用其基类中的F_Out
时,程序还不知道OutPut
的具体引用地址。查找后发现这个虚方法的第一个重写就是Sub
中的OutPut
,因此,就开始执行它了。个人浅见,我会把这个问题分享给身边同事。如果有更深入的理解,我会及时更新。