方法繼承
第一等的面向對象機制為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
我們可以看到class Child中F()方法的聲明采取了重寫(new)的辦法來屏蔽class Parent中的非虛方法F()的聲明。而G()方法就采用了覆蓋(override)的辦法來提供方法的多態機制。需要注意的是重寫(new)方法和覆蓋(override)方法的不同,從本質上講重寫方法是編譯時綁定,而覆蓋方法是運行時綁定。值得指出的是虛方法不可以是靜態方法--也就是說不可以用static和virtual同時修飾一個方法,這由它的運行時類型辨析機制所決定。override必須和virtual配合使用,當然也不能和static同時使用。
那麼我們如果在一個類的繼承體系中不想再使一個虛方法被覆蓋,我們該怎樣做呢?答案是sealed override (密封覆蓋),我們將sealed和override同時修飾一個虛方法便可以達到這種目的:sealed override public void F()。注意這裡一定是sealed和override同時使用,也一定是密封覆蓋一個虛方法,或者一個被覆蓋(而不是密封覆蓋)了的虛方法。密封一個非虛方法是沒有意義的,也是錯誤的。看下面的例子:
//sealed.cs
// csc /t:library sealed.cs
using System;
class Parent
{
public virtual void F()
{
Console.WriteLine("Parent.F");
}
public virtual void G()
{
Console.WriteLine("Parent.G");
}
}
class Child: Parent
{
sealed override public void F()
{
Console.WriteLine("Child.F");
}
override public void G()
{
Console.WriteLine("Child.G");
}
}
class Grandson: Child
{
override public void G()
{
Console.WriteLine("Grandson.G");
}
}