一、抽象類:
抽象類是特殊的類宏邮,只是不能被實例化泽示;除此以外,具有類的其他特性蜜氨;重要的是抽象類可以包括抽象方法械筛,這是普通類所不能的。抽象方法只能聲明于抽象類中飒炎,且不包含任何實現(xiàn)埋哟,派生類必須覆蓋它們。另外郎汪,抽象類可以派生自一個抽象類赤赊,可以覆蓋基類的抽象方法也可以不覆蓋,如果不覆蓋煞赢,則其派生類必須覆蓋它們抛计。
二、接口:
接口是引用類型的照筑,類似于類,和抽象類的相似之處有三點:
1吹截、不能實例化;
2凝危、包含未實現(xiàn)的方法聲明波俄;
3、派生類必須實現(xiàn)未實現(xiàn)的方法蛾默,抽象類是抽象方法懦铺,接口則是所有成員(不僅是方法包括其他成員);
另外支鸡,接口有如下特性:
接口除了可以包含方法之外冬念,還可以包含屬性、索引器牧挣、事件刘急,而且這些成員都被定義為公有的。除此之外浸踩,不能包含任何其他的成員叔汁,例如:常量、域、構(gòu)造函數(shù)据块、析構(gòu)函數(shù)码邻、靜態(tài)成員。一個類可以直接繼承多個接口另假,但只能直接繼承一個類(包括抽象類)像屋。
三、抽象類和接口的區(qū)別:
1.類是對對象的抽象边篮,可以把抽象類理解為把類當(dāng)作對象己莺,抽象成的類叫做抽象類.而接口只是一個行為的規(guī)范或規(guī)定,微軟的自定義接口總是后帶able字段戈轿,證明其是表述一類類“我能做凌受。。思杯∈を龋”.抽象類更多的是定義在一系列緊密相關(guān)的類間,而接口大多數(shù)是關(guān)系疏松但都實現(xiàn)某一功能的類中.
2.接口基本上不具備繼承的任何具體特點,它僅僅承諾了能夠調(diào)用的方法;
3.一個類一次可以實現(xiàn)若干個接口,但是只能擴展一個父類
4.接口可以用于支持回調(diào),而繼承并不具備這個特點.
5.抽象類不能被密封色乾。
6.抽象類實現(xiàn)的具體方法默認(rèn)為虛的誊册,但實現(xiàn)接口的類中的接口方法卻默認(rèn)為非虛的,當(dāng)然您也可以聲明為虛的.
7.(接口)與非抽象類類似暖璧,抽象類也必須為在該類的基類列表中列出的接口的所有成員提供它自己的實現(xiàn)案怯。但是,允許抽象類將接口方法映射到抽象方法上澎办。
8.抽象類實現(xiàn)了oop中的一個原則嘲碱,把可變的與不可變的分離。抽象類和接口就是定義為不可變的浮驳,而把可變的座位子類去實現(xiàn)悍汛。
9.好的接口定義應(yīng)該是具有專一功能性的捞魁,而不是多功能的至会,否則造成接口污染。如果一個類只是實現(xiàn)了這個接口的中一個功能谱俭,而不得不去實現(xiàn)接口中的其他方法奉件,就叫接口污染。
10.盡量避免使用繼承來實現(xiàn)組建功能昆著,而是使用黑箱復(fù)用县貌,即對象組合。因為繼承的層次增多凑懂,造成最直接的后果就是當(dāng)你調(diào)用這個類群中某一類煤痕,就必須把他們?nèi)考虞d到棧中!后果可想而知.(結(jié)合堆棧原理理解)。同時摆碉,有心的朋友可以留意到微軟在構(gòu)建一個類時塘匣,很多時候用到了對象組合的方法。比如asp.net中巷帝,Page類忌卤,有Server Request等屬性,但其實他們都是某個類的對象楞泼。使用Page類的這個對象來調(diào)用另外的類的方法和屬性驰徊,這個是非常基本的一個設(shè)計原則堕阔。
11.如果抽象類實現(xiàn)接口棍厂,則可以把接口中方法映射到抽象類中作為抽象方法而不必實現(xiàn),而在抽象類的子類中實現(xiàn)接口中方法.
四印蔬、抽象類和接口的使用:
1. 如果預(yù)計要創(chuàng)建組件的多個版本勋桶,則創(chuàng)建抽象類。抽象類提供簡單的方法來控制組件版本侥猬。
2.如果創(chuàng)建的功能將在大范圍的全異對象間使用例驹,則使用接口。如果要設(shè)計小而簡練的功能塊退唠,則使用接口鹃锈。
3.如果要設(shè)計大的功能單元,則使用抽象類.如果要在組件的所有實現(xiàn)間提供通用的已實現(xiàn)功能瞧预,則使用抽象類屎债。
4.抽象類主要用于關(guān)系密切的對象;而接口適合為不相關(guān)的類提供通用功能垢油。
以下是我在網(wǎng)上看到的幾個形象比喻,真的非常不錯,呵呵:
1.飛機會飛盆驹,鳥會飛,他們都繼承了同一個接口“飛”滩愁;但是F22屬于飛機抽象類躯喇,鴿子屬于鳥抽象類。
2. 就像鐵門木門都是門(抽象類)硝枉,你想要個門我給不了(不能實例化)廉丽,但我可以給你個具體的鐵門或木門(多態(tài));而且只能是門妻味,你不能說它是窗(單繼承)正压;一個門可以有鎖(接口)也可以有門鈴(多實現(xiàn))。門(抽象類)定義了你是什么责球,接口(鎖)規(guī)定了你能做什么(一個接口最好只能做一件事焦履,你不能要求鎖也能發(fā)出聲音吧(接口污染)拓劝。
http://kb.cnblogs.com/page/41836/
Net提供了接口,這個不同于Class或者Struct的類型定義嘉裤。接口有些情況凿将,看似和抽象類一樣,因此有些人認(rèn)為在.Net可以完全用接口來替換抽象類价脾。其實不然牧抵,接口和抽象類各有長處和缺陷,因此往往在應(yīng)用當(dāng)中侨把,兩者要結(jié)合來使用犀变,從而互補長短。
接下來先說說抽象類和接口的區(qū)別秋柄。
區(qū)別一获枝,兩者表達(dá)的概念不一樣。抽象類是一類事物的高度聚合骇笔,那么對于繼承抽象類的子類來說省店,對于抽象類來說,屬于“是”的關(guān)系笨触;而接口是定義行為規(guī)范懦傍,因此對于實現(xiàn)接口的子類來說,相對于接口來說芦劣,是“行為需要按照接口來完成”粗俱。這些聽起來有些虛,舉個例子虚吟。例如寸认,狗是對于所有狗類動物的統(tǒng)稱,京哈是狗串慰,牧羊犬是狗偏塞,那么狗的一般特性,都會在京哈邦鲫,牧羊犬中找到灸叼,那么狗相對于京哈和牧羊犬來說,就屬于這類事物的抽象類型掂碱;而對于“叫”這個動作來說怜姿,狗可以叫慎冤,鳥也可以叫疼燥。很明顯,前者相當(dāng)于所說的是抽象類蚁堤,而后者指的就是接口醉者。
區(qū)別二但狭,抽象類在定義類型方法的時候,可以給出方法的實現(xiàn)部分撬即,也可以不給出立磁;而對于接口來說,其中所定義的方法都不能給出實現(xiàn)部分剥槐。
例如:
public abstract class AbsTest
{
public virtual void Test()
{
Debug.WriteLine( "Test" );
}
public abstract void NewTest();
}
public interface ITest
{
void Test();
void NewTest();
}
區(qū)別三唱歧,繼承類對于兩者所涉及方法的實現(xiàn)是不同的。繼承類對于抽象類所定義的抽象方法粒竖,可以不用重寫颅崩,也就是說,可以延用抽象類的方法蕊苗;而對于接口類所定義的方法或者屬性來說沿后,在繼承類中必須要給出相應(yīng)的方法和屬性實現(xiàn)。
區(qū)別四朽砰,在抽象類中尖滚,新增一個方法的話,繼承類中可以不用作任何處理瞧柔;而對于接口來說漆弄,則需要修改繼承類,提供新定義的方法造锅。
知道了兩者的區(qū)別置逻,再來說說,接口相對于抽象類的優(yōu)勢备绽。
好處一券坞,接口不光可以作用于引用類型,也可以作用于值類型肺素。而抽象類來說恨锚,只能作用于引用類型。
好處二倍靡,.Net的類型繼承只能是單繼承的猴伶,也就是說一個類型只能繼承一個類型,而可以繼承多個接口塌西。其實他挎,我對于這一點也比較贊同,多繼承會使繼承樹變的混亂捡需。
好處三办桨,由于接口只是定義屬性和方法,而與真正實現(xiàn)的類型沒有太大的關(guān)系站辉,因此接口可以被多個類型重用呢撞。相對于此损姜,抽象類與繼承類的關(guān)系更緊密些。
好處四殊霞,通過接口摧阅,可以減少類型暴露的屬性和方法,從而便于保護(hù)類型對象绷蹲。當(dāng)一個實現(xiàn)接口的類型棒卷,可能包含其他方法或者屬性,但是方法返回的時候祝钢,可以返回接口對象娇跟,這樣調(diào)用端,只能通過接口提供的方法或者屬性太颤,訪問對象的相關(guān)元素苞俘,這樣可以有效保護(hù)對象的其他元素。
好處五龄章,減少值類型的拆箱操作吃谣。對于Struct定義的值類型數(shù)據(jù),當(dāng)存放集合當(dāng)中做裙,每當(dāng)取出來岗憋,都需要進(jìn)行拆箱操作,這時采用Struct+Interface結(jié)合的方法锚贱,從而降低拆箱操作仔戈。
參看如下文章提供的方法。
http://blog.csdn.net/Knight94/archive/2006/10/08/1326326.aspx
相對于抽象類來說拧廊,接口有這么多好處监徘,但是接口有一個致命的弱點,就是接口所定義的方法和屬性只能相對于繼承它的類型(除非在繼承類中修改借口定義的函數(shù)標(biāo)示)吧碾,那么對于多層繼承關(guān)系的時候凰盔,光用接口就很難實現(xiàn)。因為如果讓每個類型都去繼承接口而進(jìn)行實現(xiàn)的話倦春,首先不說編寫代碼比較繁瑣户敬,有時候執(zhí)行的結(jié)果還是錯誤,尤其當(dāng)子類型對象隱式轉(zhuǎn)換成基類對象進(jìn)行訪問的時候睁本。
那么這時候尿庐,需要用接口結(jié)合虛方法來實現(xiàn)。參看IDisposable在繼承類型中的實現(xiàn)方法呢堰。
http://blog.csdn.net/Knight94/archive/2006/10/10/1329214.aspx
其實在繼承中抄瑟,到底使用接口還是抽象類。接口是固定的暮胧,約定俗成的锐借,因此在繼承類中必須提供接口相應(yīng)的方法和屬性的實現(xiàn)。而對于抽象類來說往衷,抽象類的定義方法的實現(xiàn)钞翔,貫穿整個繼承樹,因此其中方法的實現(xiàn)或者重寫都是不確定的席舍。因此相對而言布轿,抽象類比接口更靈活一些。
如下給出兩者的簡單對比表格来颤。
接口 抽象類
多繼承 支持 不支持
類型限制 沒有 有汰扭,只能是引用類型
方法實現(xiàn) 繼承類型中必須給出方法實現(xiàn) 繼承類中可以不給出
擴展性 比較麻煩 相對比較靈活
多層繼承 比較麻煩,需要借助虛函數(shù) 比較靈活
總的來說福铅,接口和抽象類是.Net為了更好的實現(xiàn)類型之間繼承關(guān)系而提供的語言手段萝毛,而且兩者有些相輔相成的關(guān)系。因此我并不強調(diào)用什么而不用什么滑黔,那么問題的關(guān)鍵在于笆包,如何把這兩種手段合理的應(yīng)用到程序當(dāng)中,這才是至關(guān)重要略荡。