OOP的多型和繼承
在OOP中,繼承有如下的定義:
繼承是一種OOP的機制,用於派生繼承預定義的類
在這個繼承關係中,預定義的類是基類,新類是子類
繼承常常用於實現程式碼重用
繼承允許子類複用基類非private的的資料和方法
繼承的實現
建立一個Console工程,命名為InheritanceAndPolymorphism。新增ClassA、ClassB類,並複製下面的程式碼:
ClassA: class ClassA { } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
在Program.cs中,呼叫ClassA
class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); } }
如果執行,肯定會報錯的。
Error:
'InheritanceAndPolymorphism.ClassA
' does not contain a definition for 'Display1
' and no extension method 'Display1
' accepting a first argument of type 'InheritanceAndPolymorphism.ClassA
' could be found
因為我們在ClassA中未定義Display1的方法。 下面我們重寫,使ClassA繼承自ClassB。
ClassA: class ClassA:ClassB { } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
再次執行,結果如下:
ClassB Display1
ClassA已經可以訪問其基類的Display1函式了,這個簡單的例項說明了繼承可複用基類的妙處。
再來看另外一個場景,假設ClassA也有一個Display1函式,簽名和其基類一樣的:
class ClassA:ClassB { public void Display1() { System.Console.WriteLine("ClassA Display1"); } } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
執行後結果如下:
ClassA Display1
看起來結果是對的,ClassA預設呼叫了自己的Display1函式,但是Visual Studio有一個警告:
Warning: '
InheritanceAndPolymorphism.ClassA.Display1()
' hides inherited member 'InheritanceAndPolymorphism.ClassB.Display1()
'. Use thenew
keyword if hiding was intended.
C#中對方法的呼叫首先是查詢ClassA自己中有無Display1函式,再查詢其基類有無Display1函式。在基類和子類出現同樣函式的情況現實專案中是存在的,可能是基類程式碼過於陳舊了,子類既想用同簽名的函式,又無法停止基類的同簽名函式,故會出現這樣的警告---儘管邏輯正確,但是這種設計還是有一些瑕疵的。
我們再試試在CalssA中透過base呼叫基類同名方法的情況:
ClassA: class ClassA:ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display1(); } } ClassB: class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } }
執行結果如下:
ClassA Display1
ClassB Display1
這個實驗說明C#提供了base關鍵詞,用於在繼承中子類呼叫基類的函式或者變數(非private型別)。
同樣的,在ClassA.Display1中呼叫其基類的Display2也是可以的,程式碼如下所示:
////// ClassB: acting as base class /// class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } } ////// ClassA: acting as derived class /// class ClassA : ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display2(); } } ////// Program: used to execute the method. /// Contains Main method. /// class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); Console.ReadKey(); } }
執行結果如下:
ClassA Display1
ClassB Display2
那麼可否透過基類呼叫其子類的函式呢?
////// ClassB: acting as base class /// class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } } ////// ClassA: acting as derived class /// class ClassA : ClassB { public void Display2() { Console.WriteLine("ClassA Display2"); } } ////// Program: used to execute the method. /// Contains Main method. /// class Program { static void Main(string[] args) { ClassB b = new ClassB(); b.Display2(); Console.ReadKey(); } }
執行報錯:
Error: 'InheritanceAndPolymorphism.ClassB
' does not contain a definition for 'Display2
' and no extension method 'Display2
' accepting a first argument of type 'InheritanceAndPolymorphism.ClassB
' could be found
原因是繼承無法實現逆向呼叫,既基類無法呼叫子類。
除了建構函式和解構函式,子類繼承了其基類的一些(包括private的成員變數和成員函式,只是無法訪問)。
在C#中,一個類預設繼承的是object型別,object是C#所有引用型別的基類;同時,繼承具有傳遞性,如ClassC繼承自ClassB,ClassB繼承自ClassA,則ClassC可完全複用ClassA的資料和函式---ClassC繼承了ClassA。
C#中所有的型別都可被繼承嗎?
public class ClassW : System.ValueType { } public class ClassX : System.Enum { } public class ClassY : System.Delegate { } public class ClassZ : System.Array { }
執行結果:
'InheritanceAndPolymorphism.ClassW' cannot derive from special class 'System.ValueType'
'InheritanceAndPolymorphism.ClassX' cannot derive from special class 'System.Enum'
'InheritanceAndPolymorphism.ClassY' cannot derive from special class 'System.Delegate'
'InheritanceAndPolymorphism.ClassZ' cannot derive from special class 'System.Array'
執行的結果讓人抓狂
在C#中,自定義類無法繼承自C#內建的一些類,如System.ValueType
, System.Enum
, System.Delegate
, System.Array
, etc。
下面這個例子我們再看看C++中的多類繼承是否可在C#中實現:
public class ClassW { } public class ClassX { } public class ClassY : ClassW, ClassX { }
執行結果:
Compile time Error: Class 'InheritanceAndPolymorphism.ClassY
' cannot have multiple base classes: 'InheritanceAndPolymorphism.ClassW
' and 'ClassX
'.
執行結論是:C#僅支援單類繼承,不支援C++的這種星型繼承關係。 要使用星型繼承關係,請用介面實現。
那麼可否實現迴圈依賴繼承呢?
public class ClassW: ClassY { } public class ClassX: ClassW { } public class ClassY : ClassX { }
程式碼邏輯很簡單,ClassW繼承自ClassY,ClassX繼承自ClassW, ClassY繼承自ClassX。
但是編譯後報錯了:
Error: Circular base class dependency involving 'InheritanceAndPolymorphism.ClassX
' and 'InheritanceAndPolymorphism.ClassW
'.
我們得出一個結論,C#中不許環形依賴繼承。
例項物件的是否可賦值
ClassB: public class ClassB { public int b = 100; } ClassA: public class ClassA { public int a = 100; }
Program.cs 程式碼如下
////// Program: used to execute the method. /// Contains Main method. /// public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
我們嘗試判斷ClassA、ClassB的物件是否可賦值。
編譯的結果是:報錯了
Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA' Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
儘管ClassA和ClassB裡面的資料成員變數a資料一致,都為100,但是這裡用等號比較的是型別--引用地址,故無法進行賦值。
我們再來試試繼承關係的:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } ////// Program: used to execute the method. /// Contains Main method. /// public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
ClassA繼承自ClassB,我們希望可以直接賦值其例項物件。
執行結果如下:
Error: Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB
' to 'InheritanceAndPolymorphism.ClassA
'.
執行結論:C#中子類物件可直接賦值給基類物件,基類物件需要往下強轉。程式碼修改如下:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } ////// Program: used to execute the method. /// Contains Main method. /// public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classB=classA; classA = (ClassA)classB; } }
這樣編譯就透過了。
如果ClassA不繼承自ClassB,則這種強轉在C#中是會報錯的:
Cannot convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
Cannot convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'
本節結論
無法阻止子類覆蓋基類同簽名方法
繼承關係是子類的同簽名方法先查詢,再查詢其基類的
base關鍵字被C#用於在子類中呼叫基類函式、變數
繼承關係不可逆轉
除了建構函式、解構函式,子類繼承了基類的一些
自定義類預設繼承自Object型別,但是C#的這些型別不能被繼承:
System.ValueType
,System.Enum
,System.Delegate
,System.Array
, etc.C#不支援從多類繼承
C#不支援迴圈繼承
子類物件可直接賦值給基類,反之需要強轉。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4692/viewspace-2808813/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 多型和繼承多型繼承
- Python 繼承 和 多型Python繼承多型
- Python中的繼承和多型Python繼承多型
- 封裝、繼承和多型封裝繼承多型
- 實驗五 繼承和多型繼承多型
- 實驗5 繼承和多型繼承多型
- 18-oop繼承OOP繼承
- 繼承與多型繼承多型
- C#中繼承和多型的研究C#中繼繼承多型
- JavaScript 的繼承與多型JavaScript繼承多型
- Javascript的繼承與多型JavaScript繼承多型
- [c++] 繼承和多型整理二C++繼承多型
- 太極1:繼承和多型2繼承多型
- go語言中的封裝,繼承和多型Go封裝繼承多型
- java繼承與多型Java繼承多型
- TypeScript(5)類、繼承、多型TypeScript繼承多型
- Java中的類繼承與多型Java繼承多型
- 多繼承 與 多重繼承繼承
- python極簡教程07:封裝、多型和繼承Python封裝多型繼承
- 這樣理解,java繼承中多型的屬性和方法Java繼承多型
- 多繼承繼承
- aardio 實現封裝繼承多型封裝繼承多型
- C語言實現繼承多型C語言繼承多型
- 面向2-封裝、繼承、多型封裝繼承多型
- Java的三大特性:封裝、繼承、多型Java封裝繼承多型
- Go語言封裝、繼承、介面、多型和斷言的案例Go封裝繼承多型
- Java抽象類、繼承及多型和介面卡的實現Java抽象繼承多型
- Java基礎之淺談繼承、多型Java繼承多型
- 詳細介紹Python類的繼承與多型Python繼承多型
- 聊聊iOS中的多繼承和多重代理iOS繼承
- oop類的繼承與類靜態成員學習OOP繼承
- 計算機程式的思維邏輯 (15) – 初識繼承和多型計算機繼承多型
- Cris 的 Scala 筆記整理(八):物件導向中級-繼承和多型筆記物件繼承多型
- Python 簡明教程 --- 21,Python 繼承與多型Python繼承多型
- Java入門教程九(封裝繼承多型)Java封裝繼承多型
- java封裝繼承以及多型(含程式碼)Java封裝繼承多型
- python 基礎之繼承、重寫、多繼承Python繼承
- JavaScript繼承的多種方式和優缺點JavaScript繼承