繼承的本質(讀《你必須知道的.net》記錄筆記)

public abstract class Animal

 { 

public abstract void ShowType();

 public void Eat() 

  {

 Console.WriteLine("Animal always eat."); 

  }

 } 

public class Bird: Animal

 {

     private string type = "Bird"; 

    public override void ShowType() 

    {

        Console.WriteLine("Type is {0}", type);

    } 

    private string color; 

    public string Color

    { 

    get { return color; } set { color = value; }

    }

 } 

public class Chicken : Bird

 { 

     private string type = "Chicken"; 

     public override void ShowType()

     {

      Console.WriteLine("Type is {0}", type);

     }

     public void ShowColor() 

    {

        Console.WriteLine("Color is {0}", Color); 

    }

 } 

然後,在測試類中創建各個類對象,由於Animal爲抽象類,我們只創建Bird對象和Chicken對象。 

public class TestInheritance 

    public static void Main() 

    { 

        Bird bird = new Bird(); 

        Chicken chicken = new Chicken();

     } 

}

下面我們從編譯角度對這一簡單的繼承示例進行深入分析,從而瞭解.NET內部是如何實現我們強調的繼承機制的。

(1)我們簡要地分析一下對象的創建過程:

   Bird bird = new Bird();

    Bird bird創建的是一個Bird類型的引用,而new Bird()完成的是創建Bird對象,分配內存空間和初始化操作,然後將這個對象引用賦給bird變量,也就是建立bird變量與Bird對象的關聯。

(2)我們從繼承的角度來分析CLR在運行時如何執行對象的創建過程,因爲繼承的本質正體現於對象的創建過程中。

     在此我們以Chicken對象的創建爲例,首先是字段,對象一經創建,會首先找到其父類Bird,併爲其字段分配存儲空間,而Bird也會繼續找到其父類Animal,爲其分配存儲空間,依次類推直到遞歸結束,也就是完成System.Object內存分配爲止。我們可以在編譯器中用單步執行的方法來大致瞭解其分配的過程和順序,因此,對象的創建過程是按照順序完成了對整個父類及其本身字
段的內存創建,並且字段的存儲順序是由上到下排列,最高層類的字段排在最前面。其原因是如果父類和子類出現了同名字段,則在子類對象創建時,編譯器會自動認爲這是兩個不同的字段而加以區別。

  從我們的分析和上面的對象創建過程中,我們應對繼承的本質有了以下更明確的認識:
  — 繼承是可傳遞的,子類是對父類的擴展,必須繼承父類方法,同時可以添加新方法。 

   — 子類可以調用父類方法和字段,而父類不能調用子類方法和字段。 

   — 虛方法如何實現覆寫操作,使得父類指針可以指向子類對象成員。

   — 子類不光繼承父類的公有成員,同時繼承了父類的私有成員,只是在子類中不被訪問。 

   — new關鍵字在虛方法繼承中的阻斷作用。

兩個重要原則:

1.關注對象原則:調用子類還是父類的方法,取決於創建的對象是子類對象還是父類對象,而不是它的引用類型。例如Bird bird2 = new Chicken()時,我們關注的是其創建對象爲Chicken類型,因此子類將繼承父類的字段和方法,或者覆寫父類的虛方法,而不用關注bird2的引用類型是否爲Bird。引用類型的區別決定了不同的對象在方法表中不同的訪問權限。

2.執行就近原則:對於同名字段或者方法,編譯器是按照其順序查找來引用的,也就是首先訪問離它創建最近的字段或者方法,例如上例中的bird2,是Bird類型,因此會首先訪問Bird_type(注意編譯器是不會重新命名的,在此是爲區分起見),如果type類型設爲public,則在此將返回“Bird”值。這也就是爲什麼在對象創建時必須將字段按順序排列,而父類要先於子類編譯的原因了。

上面我們分析到bird2.type的值是“Bird”,那麼bird2.ShowType()會顯示什麼值呢?答案是“Type is Chicken”

(本文處:你必須知道的.NET)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章