工作好多年有可能還未真正瞭解接口和抽象類

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a9/a9f06646997fe4d6c422ff5b0b864238.png","alt":"image","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類和接口的定義和區別?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類在面向對象編程中解決了什麼問題?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"接口在面向對象編程中解決了什麼問題?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"如何決定該用抽象類還是接口?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"如果使用的語言不支持抽象類和接口,該如何應對?"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"link","attrs":{"href":"#抽象類","title":null}},{"type":"text","text":"抽象類"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在面向對象編程的語言中,多數都添加了對抽象類和接口的支持,比如最常用的java,C#等語言。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" //抽象類\n public abstract class Human\n {\n //抽象方法\n public abstract string Gender();\n //屬性\n public string Name { get; set; }\n //方法\n public int GetAge()\n {\n return 1;\n }\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上是一個普通的抽象類的定義,具體怎樣使用,度娘有一大堆結果,其實總體來說抽象類主要有以下幾點特徵:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類不能被實例化,只能被繼承。也就是說如果 New Human()會報編譯錯誤"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類也是類,可以包含屬性和方法,方法可以包含實現,也可以不包含,不包含實現被稱爲抽象方法。"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"子類繼承抽象類,必須要實現定義的所有抽象方法,不然編譯器會報編譯錯誤。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類本質上還是類,只不過是一種不能被實例化的特殊類而已,但是在面向對象的設計過程中卻起着非常重要的地位,本質上抽象類體現的是is-a的關係,就像上邊定義的抽象類一樣,Human類型抽象的是人類,假如我定義一個菜菜的類型來繼承這個類型"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" public class CaiCai : Human\n {\n public override string Gender()\n {\n return \"男\";\n }\n\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"CaiCai這個類必須要提供抽象方法的實現纔可以通過編譯。抽象類的產生是面向對象開發思想的延伸,是解決代碼複用問題的一個方案,更是把代碼進行抽象化的一個結果。抽象類的設計思想是自下而上的,也就是說設計上應該先有子類,當子類逐漸增加,進而抽象出共用特性而產生抽象類。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說到這裏,好多同學會問,如果我不用抽象類做父類也可以啊。不錯,普通的類當然也可以代替抽象類的地位。但是有幾點就看起來比較奇怪了"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"父類也可以進行實例化了,但是其中要抽象的方法看起來就比較怪了,因爲這些方法只有子類中才有明確的定義,比如 以上代碼中Human這個類如果修改爲普通類型,那方法Gender()該返回什麼內容呢?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"在編譯期間,如果子類沒有實現父類的方法是不會報錯的,這就加大了排查問題的難度,如果需要重寫的方法很多,之後排查問題會非常頭疼"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"抽象出來的父類如果可以被實例化,這本質上違反了面向對象的思想,畢竟父類是一個抽象化的概念,被實例化之後代表着什麼比較令人困惑"}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"link","attrs":{"href":"#接口","title":null}},{"type":"text","text":"接口"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接口在系統設計中,最重要的作用就是解耦。你應該聽過不止一次的“面向接口編程”和依賴倒置等思想,這些也是面向對象設計思想的一種體現。接口本質上是抽象出來的對象的行爲,或者叫做契約。在面向接口開發中,調用者不關心接口的實現,而是依賴於接口的定義,接口定義的穩定性代表着一個系統的穩定性,如果一個系統對外的接口定義有問題,那這個系統多半是會死人的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":" public interface IHuman\n {\n //接口行爲定義\n void Walk();\n }\n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上只是一個簡單接口的定義而已,接口的抽象小到可以是一個對象的行爲抽象,大到可以是一個服務的行爲抽象,更有可能是一個系統的行爲抽象,所以接口是一個很泛的概念,但是本質上還是反應的是面向對象設計理念。由於接口是行爲的定義,所以就決定了它有以下特點"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":null,"normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"接口只能定義行爲,不能包含行爲的實現"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"類型繼承接口的時候,必須要實現接口的所有行爲"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"接口不同於類,不能包含屬性"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於接口體現的是行爲準則,所以接口在定義的時候也可以利用面向對象設計理念,當多個不同接口定義了相同的行爲,可以考慮抽象出更上層的接口來實現行爲的複用。"}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"link","attrs":{"href":"#寫在最後","title":null}},{"type":"text","text":"寫在最後"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"抽象類和接口都是對象的抽象行爲產生的,只不過抽象類更加側重於 is-a 的關係,它實現了代碼複用,而接口更加側重於行爲的抽象(has -a),舉一個很簡單的栗子,如果設計一個鳥類的抽象該怎麼做呢?不同的鳥可能羽毛的顏色不一樣,像這樣的屬性可以利用抽象類,不同的鳥類可能會有不同的飛行行爲,這樣行爲類的抽象利用接口來實現更加合適。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"無論是接口還是抽象類,在代碼層次上體現的是上下級關係,就算一個編程語言沒有提供接口和抽象類的定義,只要能實現對象上下級關係,原理上也可以實現面向對象編程。編程的抽象思想始終在圍繞着上下,內外這幾個維度在合理的進化着。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說到接口的定義,其實還可以在泛化一下,接口中只有行爲方法的定義,在一些不支持接口的編程語言中,可以把只包含方法的類看做接口的抽象定義,這在設計理念上是說的通的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在繼承層次上和設計流程上,抽象類是一種自下而上的設計思路,先有子類的代碼,當子類逐漸增多,纔會抽象出更加上層的父類。而接口不同,面向接口編程是一種自上而下的設計思路,先抽象出行爲契約,然後纔是實現。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"更多精彩文章"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342955119549267969&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"分佈式大併發系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342959003139227648&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"架構設計系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342962375443529728&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"趣學算法和數據結構系列"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&album_id=1342964237798391808&__biz=MzIwNTc3OTAxOA==#wechat_redirect","title":null},"content":[{"type":"text","text":"設計模式系列"}]}]}]}]}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f8/f8af5984765a267892bf1a1272272625.png","alt":"image","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章