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