本文是深入淺出OOP第二篇,主要說(shuō)說(shuō)繼承的話(huà)題。
為洪山等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及洪山網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè)、洪山網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!在OOP中,繼承有如下的定義:
繼承是一種OOP的機(jī)制,用于派生繼承預(yù)定義的類(lèi)
在這個(gè)繼承關(guān)系中,預(yù)定義的類(lèi)是基類(lèi),新類(lèi)是子類(lèi)
繼承常常用于實(shí)現(xiàn)代碼重用
繼承允許子類(lèi)復(fù)用基類(lèi)非private的的數(shù)據(jù)和方法
創(chuàng)建一個(gè)Console工程,命名為InheritanceAndPolymorphism。添加ClassA、ClassB類(lèi),并拷貝下面的代碼:
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中,調(diào)用ClassA
class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); } }
如果運(yùn)行,肯定會(huì)報(bào)錯(cuò)的。
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
因?yàn)槲覀冊(cè)贑lassA中未定義Display1的方法。 下面我們重寫(xiě),使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"); } }
再次運(yùn)行,結(jié)果如下:
ClassB Display1
ClassA已經(jīng)可以訪(fǎng)問(wèn)其基類(lèi)的Display1函數(shù)了,這個(gè)簡(jiǎn)單的實(shí)例說(shuō)明了繼承可復(fù)用基類(lèi)的妙處,下面這張圖以父子財(cái)產(chǎn)繼承關(guān)系說(shuō)明了繼承的意義
再來(lái)看另外一個(gè)場(chǎng)景,假設(shè)ClassA也有一個(gè)Display1函數(shù),簽名和其基類(lèi)一樣的:
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"); } }
執(zhí)行后結(jié)果如下:
ClassA Display1
看起來(lái)結(jié)果是對(duì)的,ClassA默認(rèn)調(diào)用了自己的Display1函數(shù),但是Visual Studio有一個(gè)警告:
Warning: '
InheritanceAndPolymorphism.ClassA.Display1()
' hides inherited member 'InheritanceAndPolymorphism.ClassB.Display1()
'. Use thenew
keyword if hiding was intended.
C#中對(duì)方法的調(diào)用首先是查詢(xún)ClassA自己中有無(wú)Display1函數(shù),再查詢(xún)其基類(lèi)有無(wú)Display1函數(shù)。在基類(lèi)和子類(lèi)出現(xiàn)同樣函數(shù)的情況現(xiàn)實(shí)項(xiàng)目中是存在的,可能是基類(lèi)代碼過(guò)于陳舊了,子類(lèi)既想用同簽名的函數(shù),又無(wú)法停止基類(lèi)的同簽名函數(shù),故會(huì)出現(xiàn)這樣的警告---盡管邏輯正確,但是這種設(shè)計(jì)還是有一些瑕疵的。
我們?cè)僭囋囋贑alssA中通過(guò)base調(diào)用基類(lèi)同名方法的情況:
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"); } }
執(zhí)行結(jié)果如下:
ClassA Display1
ClassB Display1
這個(gè)實(shí)驗(yàn)說(shuō)明C#提供了base關(guān)鍵詞,用于在繼承中子類(lèi)調(diào)用基類(lèi)的函數(shù)或者變量(非private類(lèi)型)。
同樣的,在ClassA.Display1中調(diào)用其基類(lèi)的Display2也是可以的,代碼如下所示:
/// <summary> /// ClassB: acting as base class /// </summary> class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } public void Display2() { Console.WriteLine("ClassB Display2"); } } /// <summary> /// ClassA: acting as derived class /// </summary> class ClassA : ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display2(); } } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> class Program { static void Main(string[] args) { ClassA a = new ClassA(); a.Display1(); Console.ReadKey(); } }
執(zhí)行結(jié)果如下:
ClassA Display1
ClassB Display2
那么可否通過(guò)基類(lèi)調(diào)用其子類(lèi)的函數(shù)呢?
/// <summary> /// ClassB: acting as base class /// </summary> class ClassB { public int x = 100; public void Display1() { Console.WriteLine("ClassB Display1"); } } /// <summary> /// ClassA: acting as derived class /// </summary> class ClassA : ClassB { public void Display2() { Console.WriteLine("ClassA Display2"); } } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> class Program { static void Main(string[] args) { ClassB b = new ClassB(); b.Display2(); Console.ReadKey(); } }
運(yùn)行報(bào)錯(cuò):
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
原因是繼承無(wú)法實(shí)現(xiàn)逆向調(diào)用,既基類(lèi)無(wú)法調(diào)用子類(lèi)。
除了構(gòu)造函數(shù)和析構(gòu)函數(shù),子類(lèi)繼承了其基類(lèi)的一些(包括private的成員變量和成員函數(shù),只是無(wú)法訪(fǎng)問(wèn))。
在C#中,一個(gè)類(lèi)默認(rèn)繼承的是object類(lèi)型,object是C#所有引用類(lèi)型的基類(lèi);同時(shí),繼承具有傳遞性,如ClassC繼承自ClassB,ClassB繼承自ClassA,則ClassC可完全復(fù)用ClassA的數(shù)據(jù)和函數(shù)---ClassC繼承了ClassA。
C#中所有的類(lèi)型都可被繼承嗎?
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'
運(yùn)行的結(jié)果讓人抓狂
在C#中,自定義類(lèi)無(wú)法繼承自C#內(nèi)置的一些類(lèi),如System.ValueType
,System.Enum
,System.Delegate
,System.Array
, etc。
下面這個(gè)例子我們?cè)倏纯碈++中的多類(lèi)繼承是否可在C#中實(shí)現(xiàn):
public class ClassW { } public class ClassX { } public class ClassY : ClassW, ClassX { }
執(zhí)行結(jié)果:
Compile time Error: Class 'InheritanceAndPolymorphism.ClassY
' cannot have multiple base classes: 'InheritanceAndPolymorphism.ClassW
' and 'ClassX
'.
執(zhí)行結(jié)論是:C#僅支持單類(lèi)繼承,不支持C++的這種星型繼承關(guān)系。 要使用星型繼承關(guān)系,請(qǐng)用接口實(shí)現(xiàn)。
那么可否實(shí)現(xiàn)循環(huán)依賴(lài)?yán)^承呢?
public class ClassW: ClassY { } public class ClassX: ClassW { } public class ClassY : ClassX { }
代碼邏輯很簡(jiǎn)單,ClassW繼承自ClassY,ClassX繼承自ClassW, ClassY繼承自ClassX。
但是編譯后報(bào)錯(cuò)了:
Error: Circular base class dependency involving 'InheritanceAndPolymorphism.ClassX
' and 'InheritanceAndPolymorphism.ClassW
'.
我們得出一個(gè)結(jié)論,C#中不許環(huán)形依賴(lài)?yán)^承。
ClassB:public class ClassB { public int b = 100; } ClassA: public class ClassA { public int a = 100; }
Program.cs 代碼如下
/// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
我們嘗試判斷ClassA、ClassB的對(duì)象是否可賦值。
編譯的結(jié)果是:報(bào)錯(cuò)了
Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA' Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
盡管ClassA和ClassB里面的數(shù)據(jù)成員變量a數(shù)據(jù)一致,都為100,但是這里用等號(hào)比較的是類(lèi)型--引用地址,故無(wú)法進(jìn)行賦值。
我們?cè)賮?lái)試試?yán)^承關(guān)系的:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classA = classB; classB = classA; } }
ClassA繼承自ClassB,我們希望可以直接賦值其實(shí)例對(duì)象。
運(yùn)行結(jié)果如下:
Error: Cannot implicitly convert type 'InheritanceAndPolymorphism.ClassB
' to 'InheritanceAndPolymorphism.ClassA
'.
運(yùn)行結(jié)論:C#中子類(lèi)對(duì)象可直接賦值給基類(lèi)對(duì)象,基類(lèi)對(duì)象需要往下強(qiáng)轉(zhuǎn)。代碼修改如下:
public class ClassB { public int b = 100; } public class ClassA:ClassB { public int a = 100; } /// <summary> /// Program: used to execute the method. /// Contains Main method. /// </summary> public class Program { private static void Main(string[] args) { ClassB classB = new ClassB(); ClassA classA = new ClassA(); classB=classA; classA = (ClassA)classB; } }
這樣編譯就通過(guò)了。
如果ClassA不繼承自ClassB,則這種強(qiáng)轉(zhuǎn)在C#中是會(huì)報(bào)錯(cuò)的:
Cannot convert type 'InheritanceAndPolymorphism.ClassA' to 'InheritanceAndPolymorphism.ClassB'
Cannot convert type 'InheritanceAndPolymorphism.ClassB' to 'InheritanceAndPolymorphism.ClassA'
無(wú)法阻止子類(lèi)覆蓋基類(lèi)同簽名方法
繼承關(guān)系是子類(lèi)的同簽名方法先查找,再查找其基類(lèi)的
base關(guān)鍵字被C#用于在子類(lèi)中調(diào)用基類(lèi)函數(shù)、變量
繼承關(guān)系不可逆轉(zhuǎn)
除了構(gòu)造函數(shù)、析構(gòu)函數(shù),子類(lèi)繼承了基類(lèi)的一些
自定義類(lèi)默認(rèn)繼承自O(shè)bject類(lèi)型,但是C#的這些類(lèi)型不能被繼承:System.ValueType
,System.Enum
,System.Delegate
,System.Array
, etc.
C#不支持從多類(lèi)繼承
C#不支持循環(huán)繼承
子類(lèi)對(duì)象可直接賦值給基類(lèi),反之需要強(qiáng)轉(zhuǎn)
原文地址:Diving in OOP (Day 2): Polymorphism and Inheritance (Inheritance)
創(chuàng)新互聯(lián)www.cdcxhl.cn,專(zhuān)業(yè)提供香港、美國(guó)云服務(wù)器,動(dòng)態(tài)BGP最優(yōu)骨干路由自動(dòng)選擇,持續(xù)穩(wěn)定高效的網(wǎng)絡(luò)助力業(yè)務(wù)部署。公司持有工信部辦法的idc、isp許可證, 機(jī)房獨(dú)有T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確進(jìn)行流量調(diào)度,確保服務(wù)器高可用性。佳節(jié)活動(dòng)現(xiàn)已開(kāi)啟,新人活動(dòng)云服務(wù)器買(mǎi)多久送多久。
分享題目:深入淺出OOP(二):多態(tài)和繼承(繼承)-創(chuàng)新互聯(lián)
文章地址:http://aaarwkj.com/article38/pggsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、商城網(wǎng)站、動(dòng)態(tài)網(wǎng)站、虛擬主機(jī)、企業(yè)網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容