2011年11月25日 星期五

C#中繼承修飾符(virtual/abstract/sealed)


http://big5.china-code.net/read/7/3/140230.html

C#中繼承修飾符(virtual/abstract/sealed)


C#的方法引入了virtual、override、sealed、abstract四種修飾符來提供不同的繼承需求。類的虛方法是可以在該類的繼承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等形態。類中改變其實現的方法,當然這種改變僅限于方法體的改變,而非方法頭(方法聲明)的改變。被子類改變的虛方法必須在方法頭加上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等形態。

沒有留言:

張貼留言