请看代码:
using
System;
class Car
{
public virtual void MoveForward()
{
Console.WriteLine("Move Car forward by 1 kilometer");
}
public void Reverse()
{
Console.WriteLine("Reverse Car by 50 meters");
}
}
class FamilyCar : Car
{
public override void MoveForward()
{
Console.WriteLine("Move Family Car forward by 5 kilometers");
}
public new void Reverse()
{
Console.WriteLine("Reverse the Family Car by 200 meters");
}
}
class Tester
{
public static void Main()
{
Car myCar;
myCar = new FamilyCar();
myCar.MoveForward();
myCar.Reverse();
Console.ReadLine();
}
}
class Car
{
public virtual void MoveForward()
{
Console.WriteLine("Move Car forward by 1 kilometer");
}
public void Reverse()
{
Console.WriteLine("Reverse Car by 50 meters");
}
}
class FamilyCar : Car
{
public override void MoveForward()
{
Console.WriteLine("Move Family Car forward by 5 kilometers");
}
public new void Reverse()
{
Console.WriteLine("Reverse the Family Car by 200 meters");
}
}
class Tester
{
public static void Main()
{
Car myCar;
myCar = new FamilyCar();
myCar.MoveForward();
myCar.Reverse();
Console.ReadLine();
}
}
我们可以看到一个基类Car和一个派生类FamilyCar
基类中有两个方法MoveForward()和Reverse(),一个为虚方法,另一个为非虚方法,然后在派生类中,MoveForward被覆盖(override)了,而Reverse使用了关键字new,这个new跟我们实例化新对象的new含义不同。我们在这暂时不讨论,暂时就认为包含关键字是为了避免编译器发出警告。(我试了一下,如果不写new关键字,会有如下警告:
“warning CS0108: “FamilyCar.Reverse()”上要求关键字 new,因为它隐藏了继承成员“Car.Reverse()”)
编译结果为:
Move Family Car forward by 5 kilometers
Reverse Car by 50 meters
这说明对虚方法MoveForward()使用了动态捆绑技术,所以执行了派生类中的实现语句。而对非虚方法Reverse()没有使用动态捆绑技术,所以执行了基类中的实现语句。
那么我们要让myCar引用一个派生类对象,而我们要执行派生类的Reverse方法,该怎么办呢?那么我们就需要为Reverse方法声明为virtual,也就是跟MoveForward一样。(这里原文在语意上有一点问题,如果把基类中Reverse方法声明为virtual,而派生类中还是用new关键字,那么结果跟上面的结果是一样的,并没有满足我们的要求,其实原作者的言下之意是派生类中也跟MoveForward一样,使用override关键字)
大部分基类声明的函数都需要声明为virtual以避免上面的非虚方法Reverse所导致的问题。那么虚方法用的多,为什么不带virtual关键字的函数缺省时为非虚方法呢?且待下回说明:)
注:此文参考《C# Primer Plus 中文版》