在上一節中咱們講到抽象類和接口之間的異同,咱們一塊兒回顧下其異同。html
同:c#
一、都不能夠被實例化ide
二、都含有聲明但未實現的方法學習
三、均可以被繼承spa
四、其子類必須實現其聲明未實現的方法設計
異:code
一、接口是多繼承,抽象類是單繼承(一個類僅能繼承一個抽象類,但能夠繼承多個接口)htm
二、抽象類能夠包含實現的方法,接口不能包含實現的方法對象
三、接口支持回調,抽象類不支持blog
四、抽象類更多的定義在一些類關係緊密的類間,接口則定義在實現其某一種功能之間
抽象類和接口的異同咱們再次熟悉了一遍,今天咱們主要講的是抽象類和接口使用場景及詳講抽象類的使用方法及接口的使用方法
抽象類、普通類、接口。咱們到底何時使用哪個呢?這就很頭痛了,不是一直使用一個就是好的。每個都有每個的使用場景。下面咱們看看到底啥事時候用啥東西吧。
咱們如今假設一個場景,如今須要設計一個程序,用來描述各個動物的一些生活習性,這裏咱們就有豬、貓、狗。
不使用抽象類也不使用接口。咱們設計他們三個的各個習性,就是豬的類裏面就包含本身的習性,貓類裏面包含本身的習性,狗類裏面包含本身的習性。若是各個習性較多但也有相同的。這樣的類看起來很是的冗餘。
咱們加入抽象類(設計實現大的功能單元),定義一個抽象類-哺乳動物類,其中定義了共同的習性,走路的方法,呼吸的方法,繁衍下一代的方法。可是叫聲不同。咱們又聲明一個叫聲的方法不實現(抽象方法)。這樣再咱們去定義豬類或者狗類的時候只須要寫出不同的地方便可。這樣看起來代碼也簡潔,清楚
咱們如今改用接口(設計實現小而簡練的功能),咱們把這些動物能夠作什麼列出來,而後統一使用接口去定義公共的。好比叫聲,行走。這些功能,咱們就可使用接口來定義聲明。而後繼承再去實現。
到了這裏,咱們總結下到底咱們編寫程序爲何須要使用抽象類呢?爲何須要使用接口呢?單一用一個普通的類很差嗎?簡單又容易。其實否則。存在即合理。咱們一塊兒看看到底爲何要使用吧
爲何使用抽象類?
抽象類每每用來表徵對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不一樣,可是本質上相同的具體概念的抽象`。這樣來講若是一個類設計就是爲了給其餘類繼承的,它表明一類對象所具備的公共屬性或方法,咱們就使用抽象類。就像上門的這個例子,把一些動物共同的屬性或者方法提取出來,定義一個抽象類。代碼變的易懂,代碼冗餘減小,變得簡潔明瞭。實現了代碼複用性。
那麼爲何使用接口呢?
通俗點講就是爲了下降代碼的耦合度。接口的意義在於抽象,不拘細節,從而使同類事物在在同一高度具備通用性及可替代性。上面的例子來說,規定好了這個叫聲這個方法,那麼繼承的就去實現這個叫聲方法就行了。若是某天加入了一個新的動物,這樣咱們也不須要修改其餘的任何方面,僅繼承一下接口修改自己便可,不須要修改或改變其餘的類或者接口。系統的靈活性增長了。
這裏可能會有個問題了。既然有了抽象類爲何還要用接口呢?這會不會有點多餘?
答案確定是不會的。那麼有了抽象類爲何還要使用接口呢?咱們看看抽象類和接口的異同就很快能明白了。
一、接口提供的事統一的行爲規範,供其餘調用,而抽象類具備接口的特性同時還能夠有本身的具體實現
二、抽象類只能有一個父類,能夠實現多個接口
那麼咱們如何使用抽象類和接口呢?
就拿咱們上面舉的那個例子來編寫一段代碼:
/// <summary> /// 叫聲的接口定義 /// </summary> public interface ICry { string Cry(); } /// <summary> /// 說話的接口定義 /// </summary> public interface ISay { string Say(); } /// <summary> /// 動物抽象的抽象類 /// </summary> public abstract class Animale { /// <summary> /// 包含的實現了的方法、呼吸、走路 /// </summary> /// <returns></returns> public static string Breathe() { return "呼吸同樣"; } public static string Run() { return "走路同樣"; } /// <summary> /// 未實現的抽象方法睡覺方法 /// </summary> /// <returns></returns> public abstract string Sleep(); } /// <summary> /// 普通的類 繼承了抽象類及兩個接口 /// </summary> public class Dog: Animale,ICry, ISay { /// <summary> /// 實現重寫抽象方法睡覺 /// </summary> /// <returns></returns> public override string Sleep() { return "睡覺"; } /// <summary> /// 實現叫聲接口方法 /// </summary> /// <returns></returns> public string Cry() { return "旺旺"; } /// <summary> /// 實現說話接口方法 /// </summary> /// <returns></returns> public string Say() { return "說話"; } }
在上面的代碼中,咱們列舉出了接口的定義及抽象類、抽象方法的定義及使用。在最下面一個普通類中,咱們繼承了一個抽象類及兩個接口,能夠實現多個接口可是隻能有一個抽象父類。若是繼承兩個抽象類的話會報錯的。
抽象類關鍵字--abstract
接口關鍵字--interface
講到抽象類,咱們也能夠一塊兒看看密封類,密封類不能做爲基類,禁止派生。若是重寫了某些功能會致使編譯錯誤或者爲了防止第三方進行擴展重寫,這個時候咱們就可使用到密封類。
重點注意:
一、密封類中不能包含虛方法(Virtual)和抽象方法(abstract)。由於密封類是不能被繼承的也就沒有派生類,就不具有實現抽象方法和虛方法的機會。
二、在使用密封類(sealed)的時候,密封類將限制它的使用,如今及將來都將受到影響
三、若是實例方法包含了sealed修飾符,那麼它也必須包含override修飾符,其父類方法必須包含virtual修飾符
/// <summary> /// 普通動物類 /// </summary> public class Animals { /// <summary> /// 動物的叫聲方法,由於其派生類重寫了次方法,因此必須使用virtual修飾符 /// </summary> /// <returns></returns> public virtual string Cry() { return "叫聲"; } } /// <summary> /// 動物狗類密封類,沒法產生派生類,不能做爲基類,繼承了動物類 /// </summary> public sealed class Dog : Animals { /// <summary> /// 重寫了動物叫的方法,同時標記爲了密封方法 /// </summary> /// <returns></returns> public override sealed string Cry() { return "旺旺"; } }
在使用密封類的時候咱們須要考慮的因素須要更加的全面,更加的謹慎,以防後面從新推翻重寫。每一個東西都沒有絕對的好,只有你用的恰到好處。多思考多選擇纔是智者。
歡迎你們掃描下方二維碼,和我一塊兒學習更多的C#知識