虚拟方法virtual
被修饰为虚拟的方法,实现是可变的,派生类可以重写基类的虚拟方法,也可以不重写基类的虚拟方法
1

public class Space
2
{
3
4
public static void Main(string[] args)
5
6
7
new Order().Submit();//to default department
8
new ShipOrder().Submit();//to default Ship department
9
new InOrder().Submit();//to default department
10
new OutOrder().Submit();//to default Out department /n to default department
11
}
12
13

14

15

public class Order
16
17
18
public virtual void Submit()
19
20
System.Console.WriteLine("to default department");
21
22
23

24

public class ShipOrder : Order
25
26
public override void Submit()
27
28
System.Console.WriteLine("to default Ship department");
29
30
31

32

public class InOrder : Order
33
{
34
35
36

37

public class OutOrder : Order
38
39
40
41
System.Console.WriteLine("to default Out department");
42
base.Submit();
43
44
在以上代码中,基类Order的Submit方法被修饰为virtual的,所以ShipOrder 和OutOrder 可以重新定义Submit的具体实现(用override 关键
字),并且还可以使用关键字base来调用基类的方法。
在讲到方法重写的时候,就必须要了解对象的数据类型转换。
在数据类型中,我们知道 数据容量小的(比如int)可以被安全的转换到数据容量大的(比如long)类型,反之是不安全的。
在对象世界正好相反,数据容量大的(子类)可以被安全的转换到数据容量小的(子类的基类)类型,反之是不安全的。
所以,所有的数据类型,都可以被安全的转为object,就是这个道理。
以下代码演示了对象的数据类型转换

Order order = new ShipOrder();//可以,子类转为基类

order.Submit();//to default Ship department

System.Console.WriteLine("type is {0}", order.GetType());//type is ShipOrder

ShipOrder ship = (ShipOrder)order;//可以,order是从ShipOrder转来的,但由于是基类转子类,必须强制类型转换


System.Console.WriteLine("type is {0}", ship.GetType());//type is ShipOrder

order = new Order();

ship = (ShipOrder)order;//不可以,order中没有ShipOrder的成员,编译正确,运行错误

InOrder inorder = new InOrder();

ship = (ShipOrder)inorder;//不可以,编译错误
在金庸小说《倚天屠龙记》中描述了virtual方法的含义
只听张三丰问道:“孩儿,你看清楚了没有?”张无忌道:“看清楚了。”张三丰道:“都记得了没有?”张无忌道:“已忘记了一小半。”
张三丰道:“好,那也难为了你。你自己去想想罢。”张无忌低头默想。过了一会,张三丰问道:“现下怎样了?”张无忌道:“已忘记了一
大半。”张三丰画剑成圈,问道:“孩儿,怎样啦?”张无忌道:“还有三招没忘记。”张三丰点点头,放剑归座。张无忌在殿上缓缓踱了一
个圈子,沉思半晌,又缓缓踱了半个圈子,抬起头来,满脸喜色,叫道:“这我可全忘了,忘得乾乾净净的了。”张三丰道:“不坏,不坏!
忘得真快”

public class Shadowboxing
public virtual void 白鹤亮翅()
public virtual void 如封似闭()
public virtual void 野马分鬃()


public class Zhang : Shadowboxing//张无忌继承张三丰的拳法
public override void 白鹤亮翅()
public override void 如封似闭()
我们再来看抽象方法abstract
抽象的方法隐含的为虚拟的方法,抽象的方法要求派生类必须重写,抽象的方法没有方法体。

public abstract class Order
public abstract void Submit();




public abstract class InOrder : Order


Order定义了抽象的Submit,因此只能定义返回值,方法名称,参数列表和访问修饰。有抽象方法的类一定是抽象类(抽象类不一定需要抽象方法)
子类可以实现抽象方法,比如ShipOrder和OutOrder
子类也可以不实现抽象方法,比如InOrder
金庸同志也同时描述了一个关于abstract的例子,威震天下的独孤九剑就是典型的抽象类型
独孤大侠是绝顶聪明之人,学他的剑法,要旨是在一个‘悟’字,决不在死记硬记。等到通晓了这九剑的剑意,则无所施而不可,便是将全部
变化尽数忘记,也不相干,临敌之际,更是忘记得越干净彻底,越不受原来剑法的拘束。

public abstract class AloneSwordsmanship//独孤九剑
public abstract void 破剑式();
public abstract void 破刀式();
public abstract void 破枪式();
public abstract void 破鞭式();
public abstract void 破索式();
public abstract void 破掌式();
public abstract void 破气式();


public class Feng : AloneSwordsmanship//风清扬继承独孤九剑
public override void 破剑式()
public override void 破刀式()
public override void 破枪式()
public override void 破鞭式()
public override void 破索式()
public override void 破掌式()
public override void 破气式()

45

public class Chong : Feng//令狐冲继承风清扬
46
47
48
重写方法override
只可以重写基类为虚拟或抽象的方法
必须有相同的签名、不可以更改访问修饰、不可以更改返回值、不可以更改参数列表、不可以更改方法名称、被重写后的方法一定可以再重写
不能是静态方法static、不能是密封方法
所以严格的来讲,令狐冲从风清扬那里得到的是已经重写后的类,不是抽象方法了,风清扬从独孤九剑那里获取的才是真正的抽象剑法。
当基类中没有定义为虚拟或者抽象的方法时
一般的方法是不允许被override的。不过有时候子类一定要有自己的特色,那怎么办呢?new一个方法。

public void Send()
System.Console.WriteLine("Sendto Out department");


public class Delivery : OutOrder
public new void Send()
System.Console.WriteLine("Sendto Delivery department");
注意OutOrder 定义的Send方法没有可以重写的修饰,但子类Delivery 通过new void Send覆盖了基类的方法,因此请注意下面的调用代码

OutOrder outorder = new OutOrder();

outorder.Send();//Sendto Out department

Delivery delivery = new Delivery();

delivery.Send();//Sendto Delivery department

outorder = delivery;

outorder.Send();//注意:Sendto Out department
当子类用new覆盖了基类的方法时,若引用变量为子类,则运行的是子类的new方法;若引用变量是基类,则运行基类方法。
刚才说到了抽象方法和抽象类,我们要再次提醒,有抽象方法的一定是抽象类,但是抽象类不一定包含抽象方法。
嫁衣神功就是典型的没有抽象方法的抽象类,嫁衣神功的修练者本身不能享用嫁衣神功的威力(类不能实例化),要把功力传给他人(必须有子类继承)
以下是一个没有抽象方法的抽象类的例子:

public abstract class Contract//合同
/* public Contract()
BillCount++;
*/
//抽象类没有必要写构造函数
public string Buyer;//买方
public string Seller;//卖方
protected double CostPrice;//成本价
public double SalePrice;//销售价格
public bool CheckPrice()
return SalePrice > CostPrice;


public class SaleContract : Contract
}

本文转自shyleoking 51CTO博客,原文链接:http://blog.51cto.com/shyleoking/806279