天天看點

C#中virtual,abstract,override修飾符

C#的方法引入了virtual、override、sealed、abstract四種修飾符來提供不同的繼承需求。類的虛方法是可以在該類的繼承類中改變其實作的方法,當然這種改變僅限于方法體的改變,而非方法頭(方法聲明)的改變。被子類改變的虛方法必須在方法頭加上override來表示。當一個虛方法被調用時,該類的執行個體——亦即對象的運作時類型(run-time type)來決定哪個方法體被調用。看下面的例子:

using System;

class Parent

{ public void F() {

Console.WriteLine(“Parent.F”); }

public virtual void G() {

Console.WriteLine(“Parent.G”); }

}

class Child: Parent

{ new public void F() {

Console.WriteLine(“Child.F”); }

public override void G() {

Console.WriteLine(“Child.G”); }

}

class Test

{

static void Main()

{ Child b = new Child();

Parent a = b;

a.F();

b.F();

a.G();

b.G();

}

}

程式經編譯後執行,輸出:

Parent.F

Child.F

Child.G

Child.G

可以看到類Child中F()方法的聲明采取了重寫(new)來屏蔽父類中的非虛方法F()的聲明,而G()方法采用了覆寫(override)來提供方法的多态機制。需要注意的是重寫(new)方法和覆寫(override)的不同,從本質上講重寫方法是編譯時綁定,而覆寫方法是運作時綁定。值得指出的是虛方法不可以是靜态方法——也就是說不可以用static和virtual同時修飾一個方法,這是由它的運作時類型辨析機制所決定的。override必須和virtual配合使用,當然也就不能和static同時使用。

如果在一個類的繼承體系中不想再使一個虛方法被覆寫,該怎樣做呢?答案是sealed override(密封覆寫),用sealed和override同時修飾一個虛方法便可以達到這種目的: sealed override public void F()。注意這裡一定是sealed和override同時使用,也一定是密封覆寫一個虛方法,或者一個被覆寫(而不是密封覆寫)了的虛方法。密封一個非虛方法是沒有意義的,也是錯誤的。

抽象(abstract)方法在邏輯上類似于虛方法,隻是不能像虛方法那樣被調用,是一個接口的聲明而非實作。抽象方法沒有方法實作,也不允許這樣做。抽象方法同樣不能是靜态的。含有抽象方法的類一定是抽象類,也一定要加abstract類修飾符。但抽象類并不一定要含有抽象方法。繼承含有抽象方法的抽象類的子類必須覆寫并實作(直接使用override)該方法,或者組合使用abstract override使之繼續抽象,或者不提供任何覆寫和實作,後兩者的行為是一樣的。看下面的例子:

using System;

abstract class Parent

{ public abstract void F();

public abstract void G(); }

abstract class Child: Parent

{ public abstract override void F();}

abstract class Grandson: Child

{

public override void F()

{ Console.WriteLine(“Grandson.F”);}

public override void G()

{ Console.WriteLine(“Grandson.G”);}

}

抽象方法可以抽象一個繼承來的虛方法。抓住了運作時綁定和編譯時綁定的基本機理,便能看透方法呈現出的overload、virtual、override、sealed、abstract等形态。

繼續閱讀