談談接口和抽象類有什麼區別?Java

談談接口和抽象類有什麼區別? 默認jdk8以前

典型回答

接口和抽象類是Java面向對象設計的兩個基礎機制。

接口是對行爲的抽象,它是抽象方法的集合,利用接口可以達到API定義和實現分離的目的。接口,不能實例化;不能包含任何非常量成員,任何feld都是隱含着public static
fnal的意義;同時,沒有非靜態方法實現,也就是說要麼是抽象方法,要麼是靜態方法(jdk8)。Java標準類庫中,定義了非常多的接口,比如java.util.List。

抽象類是不能實例化的類,用abstract關鍵字修飾class,其目的主要是代碼重用。除了不能實例化,形式上和一般的Java類並沒有太大區別,可以有一個或者多個抽象方法,也可
以沒有抽象方法。抽象類大多用於抽取相關Java類的共用方法實現或者是共同成員變量,然後通過繼承的方式達到代碼複用的目的。Java標準庫中,比如collection框架,很多通用
部分就被抽取成爲抽象類,例如java.util.AbstractList。

Java類實現interface使用implements關鍵詞,繼承abstract class則是使用extends關鍵詞,我們可以參考Java標準庫中的ArrayList。

接口vs抽象類vs類

  1. 支持多重繼承:接口支持;抽象類不支持;類不支持;
  2. 支持抽象函數:接口語義上支持;抽象類支持;類不支持;
  3. 允許函數實現:接口不允許;抽象類支持;類允許;
  4. 允許實例化:接口不允許;抽象類不允許;類允許;
  5. 允許部分函數實現:接口不允許;抽象類允許;類不允許。
  6. 定義的內容:接口中只能包括public抽象函數以及public static fnal常量;抽象類與類均無任何限制。
  7. 使用時機:當想要支持多重繼承,或是爲了定義一種類型請使用接口;當打算提供帶有部分實現的“模板”類,而將一些功能需要延遲實現請使用抽象類;當你打算提供完整的具體實現請使用
    類。

面向對象設計

面向對象的基本要素:封裝繼承多態

封裝的目的是隱藏事務內部的實現細節,以便提高安全性簡化編程。封裝提供了合理的邊界,避免外部調用者接觸到內部的細節。我們在日常開發中,因爲無意間暴露了細節導致
的難纏bug太多了,比如在多線程環境暴露內部狀態,導致的併發修改問題。從另外一個角度看,封裝這種隱藏,也提供了簡化的界面避免太多無意義的細節浪費調用者的精力

繼承代碼複用的基礎機制,類似於我們對於馬、白馬、黑馬的歸納總結。但要注意,繼承可以看作是非常緊耦合的一種關係,父類代碼修改,子類行爲也會變動。在實踐中,過度
濫用繼承,可能會起到反效果

多態,你可能立即會想到重寫(override)和重載(overload)、向上轉型。簡單說,重寫是父子類中相同名字和參數的方法,不同的實現;重載則是相同名字的方法,但是不同的
參數,本質上這些方法簽名是不一樣的。

S.O.L.I.D原則

  • 單一職責(Single Responsibility),類或者對象最好是隻有單一職責,在程序設計中如果發現某個類承擔着多種義務,可以考慮進行拆分
  • 開關原則(Open-Close, Open for extension, close for modifcation),設計要對擴展開放,對修改關閉。換句話說,程序設計應保證平滑的擴展性,儘量避免因爲新增同
    類功能而修改已有實現,這樣可以少產出些迴歸(regression)問題
  • 里氏替換(Liskov Substitution),這是面向對象的基本要素之一,進行繼承關係抽象時,凡是可以用父類或者基類的地方,都可以用子類替換
  • 接口分離(Interface Segregation),我們在進行類和接口設計時,如果在一個接口裏定義了太多方法,其子類很可能面臨兩難,就是隻有部分方法對它是有意義的,這就破壞
    了程序的內聚性。對於這種情況,可以通過拆分成功能單一的多個接口,將行爲進行解耦。在未來維護中,如果某個接口設計有變,不會對使用其他接口的子類構成影響。
  • 依賴反轉(Dependency Inversion),實體應該依賴於抽象而不是實現。也就是說高層次模塊,不應該依賴於低層次模塊,而是應該基於抽象。實踐這一原則是保證產品代碼之
    間適當耦合度的法寶。

參考鏈接

歡迎關注公衆號BatFor

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章