浅谈C#中的多态及相关知识(主要内容来自msdn) -转载(benzite)
目錄:
一、抽象類
二、接口
三、抽象類和接口的使用
四、類和接口的區(qū)別
五、覆蓋與隱藏
一、?抽象類:?
?????? ?用abstract修飾的類叫抽象類。抽象類是特殊的類,只是不能被實(shí)例化;除此以外,具有類的其他特性;重要的是抽象類可以包括抽象方法,這是普通類所不能的。抽象方法只能聲明于抽象類中,且不包含任何實(shí)現(xiàn),派生類必須覆蓋它們。?
??????? 用abstract修飾的方法叫抽象方法。abstract 修飾符可以和類、方法、屬性、索引器及事件一起使用。一個(gè)抽象方法只包含方法頭而且沒有實(shí)現(xiàn)代碼。當(dāng)一個(gè)類有一個(gè)或多個(gè)抽象方法時(shí),此類本身必須聲明為abstact。一個(gè)抽象類不能實(shí)例化.因?yàn)樗袥]有實(shí)現(xiàn)的方法。
??????? 在類聲明中使用 abstract 修飾符以指示某個(gè)類只能是其他類的基類。標(biāo)記為抽象或包含在抽象類中的成員必須通過從抽象類派生的類來實(shí)現(xiàn)。
????? ?另外,抽象類可以派生自一個(gè)抽象類,可以覆蓋基類的抽象方法也可以不覆蓋,如果不覆蓋,則其派生類必須覆蓋它們。
二、接口:
?????? 接口是引用類型的,類似于類,更和抽象類有所相似,以至于很多人對(duì)抽象類和接口的區(qū)別比較模糊。和抽象類的相似之處有三點(diǎn):
1、不能實(shí)例化;
2、包含未實(shí)現(xiàn)的方法聲明;
3、派生類必須實(shí)現(xiàn)未實(shí)現(xiàn)的方法,抽象類是抽象方法,接口則是所有成員(不僅是方法包括其他成員);另外,接口有如下特性:
??????? 接口除了可以包含方法之外,還可以包含屬性、索引器、事件,而且這些成員都被定義為公有的。除此之外,不能包含任何其他的成員,例如:常量、域、構(gòu)造函數(shù)、析構(gòu)函數(shù)、靜態(tài)成員。
一個(gè)類可以直接繼承多個(gè)接口,但只能直接繼承一個(gè)類(包括抽象類)。
接口實(shí)例
?22?public?interface?ITest?
?33?{?
?4???4?//int??a?=?null;?
?5???6?int?A?
?6??7??{?
?7??8?????get;?
?8??9??}?
?9????10?
10??11?void?Test();?
11??12?event?Del?OnDel;?
12??13?int?this[int?index]?
13??14?{?
14????15?get;?
15????16?set;?
16??17?}?
1718?}?
注意!還有另外一種類不能被實(shí)例化:
所有構(gòu)造函數(shù)都被標(biāo)記為private,這種類也是不能被實(shí)例化的,嚴(yán)格的說是不能在類外被實(shí)例化,可以在此類的內(nèi)部實(shí)例化(這種方式可以用于實(shí)現(xiàn)單件設(shè)計(jì)模式)。注意一點(diǎn),這樣的類也不能夠作為基類來繼承。
三、抽象類和接口的使用
?????? ?抽象類用于部分實(shí)現(xiàn)一個(gè)類,再由用戶按需求對(duì)其進(jìn)行不同的擴(kuò)展和完善;接口只是定義一個(gè)行為的規(guī)范或規(guī)定。
抽象類在組件的所有實(shí)現(xiàn)間提供通用的已實(shí)現(xiàn)功能;接口創(chuàng)建在大范圍全異對(duì)象間使用的功能。
抽象類主要用于關(guān)系密切的對(duì)象;而接口適合為不相關(guān)的類提供通用功能。
抽象類主要用于設(shè)計(jì)大的功能單元;而接口用于設(shè)計(jì)小而簡(jiǎn)練的功能塊。
例如:
??????? Window窗體可以用抽象類來設(shè)計(jì),可以把公有操作和屬性放到一個(gè)抽象類里,讓窗體和對(duì)話框繼承自這個(gè)抽象類,再根據(jù)自己的需求進(jìn)行擴(kuò)展和完善。
打印操作可以作為一個(gè)接口提供給每個(gè)需要此功能的窗體,因?yàn)榇绑w的內(nèi)容不同,就要根據(jù)他們自己的要求去實(shí)現(xiàn)自己的打印功能。打印時(shí)只通過接口來調(diào)用,而不用在乎是那個(gè)窗體要打印。
-----------------------
四、類和接口有何區(qū)別
??????? 從書上摘下來的,還是比較好懂的:
1.抽象類是一個(gè)不完全的類,需要進(jìn)一步專業(yè)化.接口只是一個(gè)行為的規(guī)范或規(guī)定;
2.接口基本上不具備繼承的任何具體特點(diǎn),它僅僅承諾了能夠調(diào)用的方法;
3.一個(gè)類一次可以實(shí)現(xiàn)若干個(gè)接口,但是只能擴(kuò)展一個(gè)父類
4.接口可以用于支持回調(diào),而繼承并不具備這個(gè)特點(diǎn).
有些直接就是接口與類的區(qū)別.第四點(diǎn)我不是很明白......
一個(gè)類如果要實(shí)現(xiàn)某個(gè)接口,除非它實(shí)現(xiàn)了該接口中承諾的所有方法,否則(即未實(shí)現(xiàn)或者僅僅實(shí)現(xiàn)部分方法),該類必須被聲明為抽象類.而該類的子類也繼承了這一特性.
override和new的區(qū)別
new是覆蓋override是重載。???
????
“覆蓋”并不意味著“刪除”???
????
示例:
?2??class???A???
?3??{???
?4????????public???void???F()?????
?5????????{???
?6??????????????Console.WriteLine("A.F");?????
?7????????}???
?8??}???
?9??class???B:???A???
10??{???
11????????new???public???void???F()?????
12????????{?????
13??????????????Console.WriteLine("B.F");?????
14????????}???
15??}???
16??class???Test???
17??{???
18????????static???void???Main()?????
19????????{???
20??????????????B???b???=???new???B();???
21??????????????b.F();???
22??????????????A???a???=???b;?????
23??????????????a.F();???
24????????}???
25??}???
輸出為??
? B.F??
? A.F???
????
但“重載”意味著“刪除”,這就是“覆蓋”和“重載”的區(qū)別。如下列:
?1using???System;???
?2??class???A???
?3??{???
?4????????public???virtual???void???F()?????
?5????????{???
?6??????????????Console.WriteLine("A.F");?????
?7????????}???
?8??}???
?9??class???B:???A???
10??{???
11????????public???override???void???F()?????
12????????{?????
13??????????????Console.WriteLine("B.F");?????
14????????}???
15??}???
16??class???Test???
17??{???
18????????static???void???Main()?????
19????????{???
20??????????????B???b???=???new???B();???
21??????????????b.F();???
22??????????????A???a???=???b;?????
23??????????????a.F();???
24????????}???
25??}???
輸出為??
B.F??
B.F??
abstract 與 virtual
??????? abstract與virtual: 方法重寫時(shí)都使用 override 關(guān)鍵字,interface中的方法和abstract方法都要求實(shí)現(xiàn)。調(diào)用虛方法時(shí),將為重寫成員檢查該對(duì)象的運(yùn)行時(shí)類型。將調(diào)用大部分派生類中的該重寫成員,如果沒有派生類重寫該成員,則它可能是原始成員。
virtual標(biāo)記方法為虛方法
1.可在派生類中以override覆蓋此方法
2.不覆蓋也可由對(duì)象調(diào)用
3.無此標(biāo)記的方法(也無其他標(biāo)記),重寫時(shí)需用new隱藏原方法
virtual 方法
???????? 若一個(gè)實(shí)例方法的聲明中含有 virtual 修飾符,則稱該方法為虛擬方法。若其中沒有 virtual 修飾符,則稱該方法為非虛擬方法。
非虛擬方法的實(shí)現(xiàn)是不會(huì)變的:無論是在聲明它的類的實(shí)例上調(diào)用該方法還是在派生類的實(shí)例上調(diào)用,實(shí)現(xiàn)都是相同的。與此相反,一個(gè)虛擬方法的實(shí)現(xiàn)可以由派生類取代。取代所繼承的虛擬方法的實(shí)現(xiàn)的過程稱為重寫該方法(第 10.5.4 節(jié))。
在一個(gè)虛擬方法調(diào)用中,該調(diào)用所涉及的那個(gè)實(shí)例的運(yùn)行時(shí)類型確定了要被調(diào)用的究竟是該方法的哪一個(gè)實(shí)現(xiàn)。在非虛擬方法調(diào)用中,相關(guān)的實(shí)例的編譯時(shí)類型是決定性因素。準(zhǔn)確地說,當(dāng)在具有編譯時(shí)類型 C 和運(yùn)行時(shí)類型 R 的實(shí)例(其中 R 為 C 或者從 C 派生的類)上用參數(shù)列表 A 調(diào)用名為 N 的方法時(shí),調(diào)用按下述規(guī)則處理:
?????? 首先,將重載決策應(yīng)用于 C、N 和 A,以從在 C 中聲明的和由 C 繼承的方法集中選擇一個(gè)特定的方法 M。第 7.5.5.1 節(jié)對(duì)此進(jìn)行了描述。?
?????? 然后,如果 M 為非虛擬方法,則調(diào)用 M。否則(M 為虛擬方法),就會(huì)調(diào)用就 R 而言 M 的派生程度最大的那個(gè)實(shí)現(xiàn)。對(duì)于在一個(gè)類中聲明的或者由類繼承的每個(gè)虛擬方法,存在一個(gè)就該類而言的派生程度最大的實(shí)現(xiàn)。就類 R 而言虛擬方法 M 的派生度最大的實(shí)現(xiàn)按下述規(guī)則確定:?
????? ?如果 R 中含有關(guān)于 M 的 virtual 聲明,則這是 M 的派生程度最大的實(shí)現(xiàn)。否則,如果 R 中含有關(guān)于 M 的 override 聲明,則這是 M 的派生程度最大的實(shí)現(xiàn)。否則,就 R 而言 M 的派生程度最大的實(shí)現(xiàn)與就 R 的直接基類而言 M 的派生程度最大的實(shí)現(xiàn)相同。?
??????下列實(shí)例闡釋虛擬方法和非虛擬方法之間的區(qū)別:
?2class?A
?3{
?4???public?void?F()?{?Console.WriteLine("A.F");?}
?5???public?virtual?void?G()?{?Console.WriteLine("A.G");?}
?6}
?7class?B:?A
?8{
?9???new?public?void?F()?{?Console.WriteLine("B.F");?}
10???public?override?void?G()?{?Console.WriteLine("B.G");?}
11}
12class?Test
13{
14???static?void?Main()?{
15??????B?b?=?new?B();
16??????A?a?=?b;
17??????a.F();
18??????b.F();
19??????a.G();
20??????b.G();
21???}
22}
???????? 在該示例中,A 引入一個(gè)非虛擬方法 F 和一個(gè)虛擬方法 G。類 B 引入一個(gè)新的非虛擬方法 F,從而隱藏了繼承的 F,并且還重寫了繼承的方法 G。此例產(chǎn)生輸出:
A.F
B.F
B.G
B.G
??????? 請(qǐng)注意,語句 a.G() 實(shí)際調(diào)用的是 B.G 而不是 A.G。這是因?yàn)?#xff0c;對(duì)調(diào)用哪個(gè)實(shí)際方法實(shí)現(xiàn)起決定作用的是該實(shí)例的運(yùn)行時(shí)類型(即 B),而不是該實(shí)例的編譯時(shí)類型(即 A)。
由于一個(gè)類中聲明的方法可以隱藏繼承來的方法,因此同一個(gè)類中可以包含若干個(gè)具有相同簽名的虛擬方法。這不會(huì)造成多義性問題,因?yàn)槌缮潭茸畲蟮哪莻€(gè)方法外,其他方法都被隱藏起來了。在下面的示例中:
?1using?System;
?2class?A
?3{
?4???public?virtual?void?F()?{?Console.WriteLine("A.F");?}
?5}
?6class?B:?A
?7{
?8???public?override?void?F()?{?Console.WriteLine("B.F");?}
?9}
10class?C:?B
11{
12???new?public?virtual?void?F()?{?Console.WriteLine("C.F");?}
13}
14class?D:?C
15{
16???public?override?void?F()?{?Console.WriteLine("D.F");?}
17}
18class?Test
19{
20???static?void?Main()?{
21??????D?d?=?new?D();
22??????A?a?=?d;
23??????B?b?=?d;
24??????C?c?=?d;
25??????a.F();
26??????b.F();
27??????c.F();
28??????d.F();
29???}
30}
????????C 類和 D 類均含有兩個(gè)具有相同簽名的虛擬方法:A 引入的虛擬方法和 C 引入的虛擬方法。但是,由 C 引入的方法隱藏了從 A 繼承的方法。因此,D 中的重寫聲明所重寫的是由 C 引入的方法,D 不可能重寫由 A 引入的方法。此例產(chǎn)生輸出:
B.F
B.F
D.F
D.F
請(qǐng)注意,通過訪問 D 的實(shí)例(借助一個(gè)派生程度較小的類型,它的方法沒有被隱藏起來),可以調(diào)用被隱藏的虛擬方法。
五、覆蓋與隱藏
覆蓋:
覆蓋即重寫,重寫是指重寫基類的方法,在基類中的方法必須有修飾符virtual,而在子類的方法中必須指明override。
格式:
基類中:
public virtual void myMethod()
?{
?}
子類中:
public override void myMethod()
?{
?}
重寫以后,用基類對(duì)象和子類對(duì)象訪問myMethod()方法,結(jié)果都是訪問在子類中重新定義的方法,基類的方法相當(dāng)于被覆蓋掉了。
隱藏:
子類重定義父類的方法(函數(shù)聲明一致),實(shí)現(xiàn)重定義只需要加上關(guān)鍵字new;
如果沒有添加關(guān)鍵字new,那么編譯器將默認(rèn)添加new;
隱藏的成員是早綁定。
轉(zhuǎn)載于:https://www.cnblogs.com/cnkenny/archive/2007/09/29/910979.html
總結(jié)
以上是生活随笔為你收集整理的浅谈C#中的多态及相关知识(主要内容来自msdn) -转载(benzite)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步一步SharePoint 2007之
- 下一篇: [导入]第 3 章 Enterprise