虛拟方法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