冰楓論壇

標題: [C#] 物件導向 Virtual/Override/Hide 覆寫-隱藏做動規則 [打印本頁]

作者: whitefox    時間: 2023-6-14 15:51
標題: [C#] 物件導向 Virtual/Override/Hide 覆寫-隱藏做動規則
本帖最後由 whitefox 於 2023-6-15 17:26 編輯

物件導向中使用虛方法的基本型態是
1. 使用 virtual 修飾詞放在父類別方法宣告前
2. 使用 override 修飾詞放在子類別方法宣告前(或是使用new修飾詞)
覆寫:
  1. public class Vehicle
  2. {
  3.     public virtual void Run()
  4.     {
  5.         Console.WriteLine("Base Class - Vehicle Run!");
  6.     }
  7. }

  8. public class Car : Vehicle
  9. {
  10.     public override void Run()
  11.     {
  12.         Console.WriteLine("Derived Class - Car Run!");
  13.     }
  14. }
複製代碼
主程式:
  1. Vehicle v = new Car();
  2. v.Run();
複製代碼
輸出:『Derived Class - Car Run!』

以下這個不常見,軟體開發中基本不會用,若出現基本上都是錯誤情況才會誤用,這邊做個紀錄
取代掉override改用new隱藏,要用this與base區分使用基礎類別的方法還是該子類別的方法
隱藏:
  1. public class Vehicle
  2. {
  3.     public virtual void Run()
  4.     {
  5.         Console.WriteLine("Base Class - Vehicle Run!");
  6.     }
  7. }

  8. public class Car : Vehicle
  9. {
  10.     public new void Run()
  11.     {
  12.         Console.WriteLine("Derived Class - Car Run!");
  13.     }
  14. }
複製代碼
主程式:
  1. Vehicle v = new Car();
  2. v.Run();
複製代碼
輸出:『Base Class - Vehicle Run!』

以上兩個例子的主程式中,Vehicle是宣告類別,Car是實體類別
具體的虛方法執行檢查流程如下:


用以下這個例子來統整一下這個規則流程
  1. public class A
  2. {
  3.     public virtual void Func() // 注意 virtual, 表示這是一個虛方法
  4.     {
  5.         Console.WriteLine("Class A Func");
  6.     }
  7. }
  8. class B : A // 注意B是從A類別繼承, 所以A是父類別, B是子類別
  9. {
  10.     public override void Func() // 注意 override, 表示重新覆寫虛函數
  11.     {
  12.         Console.WriteLine("Class B Func");
  13.     }
  14. }
  15. class C : B // 注意C是從B類別繼承, 所以B是父類別, C是子類別
  16. {
  17. }
  18. class D : A // 注意D是從A類別繼承, 所以A是父類別, D是子類別
  19. {
  20.     public new void Func() // 注意 new,表示覆蓋父類別裡的同名方法,而不是重新覆寫
  21.     {
  22.         Console.WriteLine("Class D Func");
  23.     }
  24. }
複製代碼
主程式:
  1. A a;         // 定義一個a這個A類別的物件, 這個A就是a的宣告類別
  2. A b;         // 定義一個b這個A類別的物件, 這個A就是b的宣告類別
  3. A c;         // 定義一個c這個A類別的物件, 這個A就是c的宣告類別
  4. A d;         // 定義一個d這個A類別的物件, 這個A就是d的宣告類別

  5. a = new A(); // 實體化a物件, A是a的實體類別
  6. b = new B(); // 實體化b物件, A是b的實體類別
  7. c = new C(); // 實體化c物件, A是c的實體類別
  8. d = new D(); // 實體化d物件, A是d的實體類別

  9. a.Func();
  10. // 執行a.Func
  11. // 1.先檢查宣告類別A
  12. // 2.檢查到是虛方法
  13. // 3.轉去檢查實體類別A,為虛方法本身
  14. // 4.執行實體類別A中的方法
  15. // 5.輸出結果『Class A Func』

  16. b.Func();
  17. // 執行b.Func
  18. // 1. 先檢查宣告類別A
  19. // 2. 檢查到是虛方法
  20. // 3. 轉去檢查實體類別B,有覆寫的
  21. // 4. 執行實體類別B中的方法
  22. // 5. 輸出結果『Class B Func』

  23. c.Func();
  24. // 執行c.Func
  25. // 1. 先檢查宣告類別A
  26. // 2. 檢查到是虛方法
  27. // 3. 轉去檢查實體類別C,無覆寫的
  28. // 4. 轉去檢查類別C的父類別B, 有覆寫的方法
  29. // 5. 執行父類別B中的Func方法
  30. // 6. 輸出結果『Class B Func』

  31. d.Func();
  32. // 執行d.Func
  33. // 1. 先檢查宣告類別A
  34. // 2. 檢查到是虛方法
  35. // 3. 轉去檢查實體類別D,無覆寫的(這個地方要注意了,雖然D裡有實現Func(),但沒有使用override關鍵字,所以不會被認為是覆寫)
  36. // 4. 轉去檢查類別D的父類別A,為虛方法本身
  37. // 5. 執行父類A中的Func方法
  38. // 6. 輸出結果 『Class A Func』

  39. D d1 = new D();
  40. d1.Func();
  41. // 執行D類別裡的Func(),  輸出結果『Class D Func』
複製代碼





歡迎光臨 冰楓論壇 (https://bingfong.com/) Powered by 冰楓