首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

[你必須知道的.NET]第十五回:繼承本質論

     編輯:關於.NET

本文介紹內容

  • 什麼是繼承?
  • 繼承的實現本質

1. 引言

關於繼承,你是否駕輕就熟、了如指掌?本文不討論基本概念,回歸本質,從編譯器運行角度揭示 .NET 繼承的運行本源,發現子類別物件如何實現對父類別成員與方法的繼承,以最簡陋示例揭示繼承實質,闡述繼承機制如何被執行——對更好理解繼承,必要且必然。

2. 分析

以簡單動物繼承體系為例:

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); }
}

測試類別建立 Bird、Chicken 物件(Animal 為抽象類別)。

編譯器角度分析物件建立過程

繼承本質體現於物件建立過程。以 Chicken 物件建立為例:

  1. 欄位配置:物件建立時,先找父類別 Bird 為其欄位配置儲存空間,Bird 再找 Animal,遞歸至 System.Object 結束。欄位儲存順序由上到下,父類別在前、子類別在後。原因:若父子類別出現同名欄位,編譯器自動視為兩個不同欄位加以區別。
  2. 方法表建立:方法表在類別首次載入 CLR 時完成,物件建立時僅將 TypeHandle 指向 Loader Heap 上的方法表位址。建立過程:Chicken 先拷貝 Bird 所有方法,再與自身方法比對,覆寫虛方法以子類別方法覆蓋同名父類別方法,新增子類別方法。逐層遞歸至 Object。方法表排序亦父類別在前、子類別在後。

物件記憶體配置圖解

核心問題清晰答案

  • 繼承可傳遞,子類別擴展父類別,必須繼承父類別方法,可新增方法。
  • 子類別可調用父類別方法/欄位,父類別不可調用子類別成員。
  • 虛方法如何實現覆寫,使父類別指標指向子類別物件成員。
  • new 關鍵字在虛方法繼承中的阻斷作用。

3. 思考

Bird bird2 = new Chicken(); 情況下,bird2.ShowType() 回傳什麼?bird2.type 是什麼?兩大原則解決:

關注物件原則

調用子類別還是父類別方法,取決於建立的物件是子類別還是父類別物件,而非引用型別。Bird bird2 = new Chicken() 關注建立物件為 Chicken 型別,因此子類別繼承父類別欄位/方法或覆寫虛方法,不關注 bird2 引用型別。引用型別差異決定不同物件在方法表中不同存取權限(透過 offset 標識區分存取位址區域)。

執行就近原則

同名欄位/方法,編譯器按順序查找引用——首先存取離建立最近的欄位/方法。bird2 為 Bird 型別,優先存取 Bird.type(若 public 則回傳 "Bird")。這也是物件建立時欄位必須按順序排列、父類別先編譯的原因。

思考題

  1. bird2.type 為 "Bird",那 bird2.ShowType() 顯示什麼?答案:"Type is Chicken"。依本文分析思考原因。
  2. new 關鍵字阻斷虛方法動態調用:子類別方法標記 new 即隱藏基類別實現,實為建立同名另一方法,在動態方法表不同位址位置,父類別方法在前、子類別在後。

4. 結論

.NET 中建立類別,該類別總在繼承(最終繼承自 System.Object)。繼承是 .NET 運行機制基礎技術之一,一切皆物件,一切皆繼承。本文從基礎出發深入本質探索本源,分析疑難比較鑒別。希望每個人能尋求自己的答案,理解繼承、關注封裝、玩轉多態是理解面向物件起點,願本文為此旅程起點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved