一、繼承 什麼是繼承?繼承是兩個或多個類之間存在的依賴關係,其中被繼承的類稱為父類或基類,繼承的類稱為子類或派生類。在繼承關係中,父類是對子類的共性提取,子類是對父類的擴展。 上面設計的文字類和圖片類中存在代碼冗餘,為了去除冗餘,我通過提取共性的方式引入了第三個類,並讓其他兩個類繼承它,代碼如下: ...
一、繼承
什麼是繼承?繼承是兩個或多個類之間存在的依賴關係,其中被繼承的類稱為父類或基類,繼承的類稱為子類或派生類。在繼承關係中,父類是對子類的共性提取,子類是對父類的擴展。
1 /// <summary> 2 /// 文字 3 /// </summary> 4 public class Word 5 { 6 /// <summary> 7 /// 內容 8 /// </summary> 9 public string Content { get; set; } 10 /// <summary> 11 /// 大小(單位B) 12 /// </summary> 13 public int Size { get; set; } 14 15 public Word() { } 16 public Word(string content, int size) 17 { 18 this.Content = content; 19 this.Size = size; 20 } 21 } 22 /// <summary> 23 /// 圖片 24 /// </summary> 25 public class Picture 26 { 27 /// <summary> 28 /// 內容 29 /// </summary> 30 public string Content { get; set; } 31 /// <summary> 32 /// 大小(單位B) 33 /// </summary> 34 public int Size { get; set; } 35 /// <summary> 36 /// 地址 37 /// </summary> 38 public string Path { get; set; } 39 40 public Picture() { } 41 public Picture(string content, int size, string path) 42 { 43 this.Content = content; 44 this.Size = size; 45 this.Path = path; 46 } 47 48 /// <summary> 49 /// 圖片存儲到文件中,併為Path賦值 50 /// </summary> 51 public void StoreToFile() 52 { 53 54 } 55 }
上面設計的文字類和圖片類中存在代碼冗餘,為了去除冗餘,我通過提取共性的方式引入了第三個類,並讓其他兩個類繼承它,代碼如下:
1 /// <summary> 2 /// 信息 3 /// </summary> 4 public class Information 5 { 6 /// <summary> 7 /// 內容 8 /// </summary> 9 public string Content { get; set; } 10 /// <summary> 11 /// 大小(單位B) 12 /// </summary> 13 public int Size { get; set; } 14 15 public Information() { } 16 public Information(string content, int size) 17 { 18 this.Content = content; 19 this.Size = size; 20 } 21 } 22 /// <summary> 23 /// 文字 24 /// </summary> 25 public class Word : Information 26 { 27 public Word() { } 28 public Word(string content, int size) 29 { 30 this.Content = content; 31 this.Size = size; 32 } 33 } 34 /// <summary> 35 /// 圖片 36 /// </summary> 37 public class Picture : Information 38 { 39 /// <summary> 40 /// 地址 41 /// </summary> 42 public string Path { get; set; } 43 44 public Picture() { } 45 public Picture(string content, int size, string path) 46 { 47 this.Content = content; 48 this.Size = size; 49 this.Path = path; 50 } 51 52 /// <summary> 53 /// 圖片存儲到文件中,併為Path賦值 54 /// </summary> 55 public void StoreToFile() 56 { 57 58 } 59 } 60 /// <summary> 61 /// 實現對象 62 /// </summary> 63 public class RealizeObject 64 { 65 public Realize() 66 { 67 //Word類和Picture類繼承Information類後,Information類的Content和Size屬性就像Word類和Picture類的屬性一樣 68 Word word = new Word("book", 4); 69 Picture picture = new Picture("", 0, @"C:\Users\Images\"); 70 Information info = new Information("this is Info", 12); 71 } 72 }
通過繼承連接文字/圖片類和它們提取共性的信息類,實現了代碼的復用性,後期如果加上音頻類和視頻類也可以通過繼承復用信息類的代碼,而不用重覆編寫Content和Size屬性。
繼承的規則:
1、子類可以繼承除了父類構造函數之外的所有非私有成員。
2、子類的任意構造函數調用之前會先調用父類的預設構造函數。
3、子類的可訪問性不能高於父類,因為這樣會強制父類的可訪問性同子類的可訪問性(比如Word用public修飾,Information用internal修飾)。
4、C#不允許類的多重繼承,即一個類只能有一個直接父類(繼承引號符後面只能寫一個類)。
二、C#關鍵字:base
繼承的規則一說明子類無法使用父類的構造函數,所以我在文字類和圖片類中創建了自己的構造函數。繼承的規則二說明子類只能隱式地調用父類的預設構造函數,而無法調用父類的非預設構造函數,即無法復用父類的非預設構造函數,所以可以通過base關鍵字使子類的構造函數自定義調用父類的非預設構造函數。下麵修改文字類和圖片類使其復用父類的非預設構造函數:
1 /// <summary> 2 /// 文字 3 /// </summary> 4 public class Word : Information 5 { 6 public Word() { } 7 public Word(string content, int size) : base(content, size); 8 } 9 /// <summary> 10 /// 圖片 11 /// </summary> 12 public class Picture : Information 13 { 14 /// <summary> 15 /// 地址 16 /// </summary> 17 public string Path { get; set; } 18 19 public Picture() { } 20 public Picture(string content, int size, string path) 21 : base(content, size) 22 { 23 this.Path = path; 24 } 25 26 /// <summary> 27 /// 圖片存儲到文件中,併為Path賦值 28 /// </summary> 29 public void StoreToFile() 30 { 31 32 } 33 }
base關鍵字除了可以復用父類非預設構造函數之外,還可以復用父類的其他非私有成員(見C#多態)。
總結:base關鍵字的使用方式同this關鍵字一樣,區別在於this關鍵字指向本類,base關鍵字指向父類。
三、C#關鍵字:sealed
sealed關鍵字可以防止被繼承或者被重寫。
1 /// <summary> 2 /// 視頻類(不能被其他類繼承) 3 /// </summary> 4 public sealed class Video : Information { }
註:sealed在防止被繼承時多用於工具類。
sealed防止被重寫(見C#多態)。
四、C#關鍵字:protected
protected是專門用於繼承中的訪問修飾符,修飾在父類的成員上使其成員可被本類及其子類訪問。
註:protected多用於修飾父類的方法。
訪問修飾符直白對比:對全世界開放,使用public;只對本國開放,使用internal;只對家族開放,使用protected;只有自己知道,使用private。
五、類型之間的關係:包含
C#五大類型(類、介面、委托、枚舉、結構)之間的相互嵌套即包含關係。既可以包含已定義類型也可以直接在被包含類型內定義類型。
包含的作用同繼承一樣也是提高代碼的復用性。
1 /// <summary> 2 /// 洗衣機類 3 /// </summary> 4 public class WashingMachine 5 { 6 7 } 8 /// <summary> 9 /// 房間類 10 /// </summary> 11 public class House 12 { 13 /// <summary> 14 /// 房間類包含已定義的洗衣機類 15 /// </summary> 16 public WashingMachine washingMachine { get; set; } 17 18 /// <summary> 19 /// 直接在房間類中定義空調類 20 /// </summary> 21 public class AirConditioner 22 { 23 24 } 25 26 /// <summary> 27 /// 直接在房間類中定義性別枚舉 28 /// </summary> 29 public enum Sex { man, woman } 30 }