虚拟方法
若一个实例方法的声明中含有 virtual
修饰符,则称该方法为虚拟方法。若其中没有 virtual
修饰符,则称该方法为非虚拟方法。非虚拟方法的实现是不会变的:无论是在声明它的类的实例上调用该方法还是在派生类的实例上调用,实现都是相同的。与此相反,一个虚拟方法的实现可以由派生类取代。取代所继承的虚拟方法的实现的过程称为重写该方法。 class
A { public void F() {
Console.WriteLine("A.F"); } public virtual void
G() { Console.WriteLine("A.G"); } } class B:
A { new
public void F() {
Console.WriteLine("B.F"); } public override void G() {
Console.WriteLine("B.G"); } } class Test { static void Main()
{
B b = new
B();
A ab = b;//这里a的类型是B类对象
A a = new A();
a.F(); //打印A.F
b.F(); //打印B.F
ab.F(); //打印A.F
a.G(); //打印B.G
b.G(); //打印B.G
ab.G(); //打印B.G } }
class A { public virtual void Func() // 注意virtual,表明这是一个虚拟函数 { Console.WriteLine("Func In A"); } } class B : A // 注意B是从A类继承,所以A是父类,B是子类 { public override void Func() // 注意override ,表明重新实现了虚函数 { Console.WriteLine("Func In B"); } } class C : B // 注意C是从B类继承,所以B是父类,C是子类 { } class D : A // 注意D是从A类继承,所以A是父类,D是子类 { public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现 { Console.WriteLine("Func In D"); } } class Program { static void Main(string[] args) { A a; // 定义一个a这个A类的对象.这个A就是a的申明类 A b; // 定义一个b这个A类的对象.这个A就是b的申明类 A c; // 定义一个c这个A类的对象.这个A就是c的申明类 A d; // 定义一个d这个A类的对象.这个A就是d的申明类 a = new A(); // 实例化a对象,A是a的实例类 b = new B(); // 实例化b对象,B是b的实例类 c = new C(); // 实例化c对象,C是c的实例类 d = new D(); // 实例化d对象,D是d的实例类 a.Func(); // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A b.Func(); // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B c.Func(); // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B d.Func();
// 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法
3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载)
4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A D d1 = new D(); d1.Func(); // 执行D类里的Func(),输出结果 Func In D Console.ReadLine(); } }