java中抽象類別和介面的區別?

來源:互聯網
上載者:User

標籤:網路層   object   ash   版本   角度   解決   強制   isp   map介面   

簡單來說,介面是公開的,裡面不能有私人的方法或變數,是用於讓別人使用的,而抽象類別是可以有私人方法或私人變數的,
另外,實現介面的一定要實現介面裡定義的所有方法,而實現抽象類別可以有選擇地重寫需要用到的方法,
一般的應用裡,最頂級的是介面,然後是抽象類別實現介面,最後才到具體類實現。
還有,介面可以實現多重繼承,而一個類只能繼承一個超類,
但可以通過繼承多個介面實現多重繼承,
介面還有標識(裡面沒有任何方法,如Remote介面)和資料共用(裡面的變數全是常量)的作用.

介面和抽象類別都是繼承樹的上層,他們的共同點如下:

1) 都是上層的抽象層。
2) 都不能被執行個體化
3) 都能包含抽象的方法,這些抽象的方法用於描述類具備的功能,但是不比提供具體的實現。

他們的區別如下:

1) 在抽象類別中可以寫非抽象的方法,從而避免在子類中重複書寫他們,這樣可以提高代碼的複用性,這是抽象類別的優勢;介面中只能有抽象的方法。

2) 一個類只能繼承一個直接父類,這個父類可以是具體的類也可是抽象類別;但是一個類可以實現多個介面。

Java語言中類的繼承是單繼承原因是:

當子類重寫父類方法的時候,或者隱藏父類的成員變數以及靜態方法的時候,JVM使用不同的綁定規則。

如果一個類有多個直接的父類,那麼會使綁定規則變得更複雜。為了簡化軟體的體繫結構和綁定機制,java語言禁止多繼承。

介面可以多繼承,是因為介面中只有抽象方法,沒有靜態方法和非常量的屬性,

只有介面的實作類別才會重寫介面中方法。因此一個類有多個介面也不會增加JVM的綁定機制和複雜度。

對於已經存在的繼承樹,可以方便的從類中抽象出新的介面,但是從類中抽象出新的抽象類別就不那麼容易了,因此介面更有利於軟體系統的維護和重構。


這是初學者經常會遇到的問題,看到這個問題,自己想起來以前痛苦的學習過程。

簡單的回答一下。介面和抽象類別之間有沒有區別?可以肯定的回答:有區別。

那既然有區別,我們不妨帶著疑問去探索一下,語言設計者們在設計介面和抽象類別時為什麼要設計出區別,他們的目的何在。

程式設計語言的設計其實也是一門哲學。

首先介面和抽象類別的設計目的就是不一樣的。介面是對動作的抽象,而抽象類別是對根源的抽象


對於抽象類別,比如男人,女人這兩個類,那我們可以為這兩個類設計一個更進階別的抽象類別--人。

對於介面,我們可以坐著吃飯,可以站著吃飯,可以用筷子吃飯,可以用叉子吃飯,甚至可以學三哥一樣用手抓著吃飯,那麼可以把這些吃飯的動作抽象成一個介面--吃飯。

所以在進階語言中(如Java,C#),一個類只能繼承一個抽象類別(因為你不可能同時是生物又是非生物)。

但是一個類可以同時實現多個介面,比如開車介面,滑冰介面,啪啪啪介面,踢足球介面,遊泳介面。

總結幾句話來說:

1、抽象類別和介面都不能被直接執行個體化,如果二者要執行個體化,就涉及到多態,不懂多態的參見我的回答JAVA的多態用幾句話能直觀的解釋一下嗎? - 知乎。

如果抽象類別要執行個體化,那麼抽象類別定義的變數必須指向一個子類對象,這個子類繼承了這個抽象類別並實現了這個抽象類別的所有抽象方法。

如果介面要執行個體化,那麼這個介面定義的變數要指向一個子類對象,這個子類必須實現了這個介面所有的方法。

2、抽象類別要被子類繼承,介面要被子類實現。

3、介面裡面只能對方法進行聲明,抽象類別既可以對方法進行聲明也可以對方法進行實現。

4、抽象類別裡面的抽象方法必須全部被子類實現,如果子類不能全部實現,那麼子類必須也是抽象類別。介面裡面的方法也必須全部被子類實現,如果子類不能實現那麼子類必須是抽象類別。

5、介面裡面的方法只能聲明,不能有具體的實現。這說明介面是設計的結果,抽象類別是重構的結果。

6、抽象類別裡面可以沒有抽象方法。

7、如果一個類裡面有抽象方法,那麼這個類一定是抽象類別。

8、抽象類別中的方法都要被實現,所以抽象方法不能是靜態static,也不能是私人的private。

9、介面(類)可以繼承介面,甚至可以繼承多個介面。但是類只能繼承一個類。

10、抽象層級(從高到低):介面>抽象類別>實作類別。

11、抽象類別主要是用來抽象類別,介面主要是用來抽象方法功能。當你關注事物的本質的時候,請用抽象類別;當你關注一種操作的時候,用介面。

12、抽象類別的功能應該要遠多於介面,但是定義抽象類別的代價較高。

因為進階語言一個類只能繼承一個父類,即你在設計這個類的時候必須要抽象出所有這個類的子類所具有的共同屬性和方法;

但是類(介面)卻可以繼承多個介面,因此每個介面你只需要將特定的動作方法抽象到這個介面即可。

也就是說,介面的設計具有更大的可擴充性,而抽象類別的設計必須十分謹慎。


在實際使用中,使用抽象類別,也就是繼承,是一種強耦合的設計,用來描述“A is a B” 的關係,即如果說A繼承於B,那麼在流程中將A當做B去使用應該完全沒有問題。

比如在Android中,各種控制項都可以被當做View去處理。

如果在你設計中有兩個類型的關係並不是“is a”,而是“is like a”,那就必須謹慎考慮繼承。

例如我前兩天看到的一個架構中的直播流量控制器(LiveStreamController)和視頻控制器(CameraVideoController),

雖然它們的生命週期很類似:接受介面控制,擁有開始、停止、暫停等狀態函數。

但很明顯它們所掌握的資源和負責的功能都是完全不一樣的,如果這時候僅僅因為長得像就覺得要去搞個“Controller”基類來歸一化處理,只能是給自己找麻煩。

這兩個類型很明顯是一個組合的關係,即LiveStreamController持有CameraVideoController對象,根據介面傳來的指令控制CameraVideoController的狀態。

而介面則多用於描述各個類型的對象間所共有的行為,表示“所有實現了這個介面的類的對象都能這麼幹”。

非常典型的就是各種用戶端編程裡面的按鈕點擊監聽(OnClickListener,TouchListener等等),

這個介面,可以由任何類型實現,表示“這個類的對象可以處理按鈕點擊事件”,

至於它是Activity、還是Fragment、還是匿名內部類,對於持有引用的View來說,一毛錢關係都沒有,

它只要在點擊事件觸發時執行實現了OnClickListener的XXXX類對象的 onClick()方法,然後就執行到 onClick()方法中的實現了。

換句話說,所有實現了OnClickListener的類的對象,都可以讓View “onClick”;

同理,比如我們在編寫應用網路層架構的時候,所有實現了RequestCallback(自己寫的回調介面)的類的對象,都可以讓Request “Callback”,這就是所謂 “共有的行為”。

  • 介面中所有的方法隱含的都是抽象的。而抽象類別則可以同時包含抽象和非抽象的方法。
  • 類可以實現很多個介面,但是只能繼承一個抽象類別
  • 類如果要實現一個介面,它必須要實現介面聲明的所有方法。但是,類可以不實現抽象類別聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。
  • 抽象類別可以在不提供介面方法實現的情況下實現介面。
  • Java介面中聲明的變數預設都是final的。抽象類別可以包含非final的變數。
  • Java介面中的成員函數預設是public的。抽象類別的成員函數可以是private,protected或者是public。
  • 介面是絕對抽象的,不可以被執行個體化。抽象類別也不可以被執行個體化,但是,如果它包含main方法的話是可以被調用的。

本身的設計目的就是不同的。

我一直認為,工科的知識有個很明顯的特點:“以用為本”。在討論介面和抽象類別的區別時,我也想從“用”的角度試著總結一下區別,所以我想到了設計目的。

介面的設計目的,是對類的行為進行約束(更準確的說是一種“有”約束,因為介面不能規定類不可以有什麼行為),也就是提供一種機制,可以強制要求不同的類具有相同的行為。

它只約束了行為的有無,但不對如何?行為進行限制。對“介面為何是約束”的理解,我覺得配合泛型食用效果更佳。

而抽象類別的設計目的,是代碼複用。

當不同的類具有某些相同的行為(記為行為集合A),且其中一部分行為的實現方式一致時(A的非真子集,記為B),可以讓這些類都派生於一個抽象類別。

在這個抽象類別中實現了B,避免讓所有的子類來實現B,這就達到了代碼複用的目的。

而A減B的部分,留給各個子類自己實現。正是因為A-B在這裡沒有實現,所以抽象類別不允許執行個體化出來(否則當調用到A-B時,無法執行)。

1.介面的所有方法都必須是抽象方法,抽象類別裡可以有非抽象方法

2.介面的所有方法與屬性都是公有的,抽象類別可以有私人的屬性和方法

3.普通類如果要實現介面的話,就必須實現介面的所有方法,但可以把普通類定義為抽象類別來選擇性重寫介面的方法.

4.對普通類而言介面的所有方法都必須被實現,而抽象類別的抽象方法必須被實現,非抽象方法可以不被實現.

5.普通類可以對介面可以實現多繼承,對抽象類別只能繼承一個,但是抽象類別可以繼承多個介面來實現多繼承


區別大家已經說了:最主要的就是JAVA不能多繼承,但是可以實現多個介面。

其它次要的比如抽象類別可以有變數,介面不能有啊;介面的方法全部得是公有的,抽象類別可以是私人的啊。

記住最主要的區別就行,實際情況下你寫一年代碼也不會寫一個抽象類別,介面倒是會寫不少。

那個被用爛了的例子是:天鵝繼承鳥類。天鵝是鳥的子類 , 天鵝可以飛,飛是一種可以可以拿出來的共同的屬性,比如蜜蜂也可以飛。 這可能是含義上的區別。

拋開多繼承,這倆貨現實意義區別沒有想象的大。

物件導向語言的出現主要是為瞭解決複用和封裝問題。

只不過思想被慢慢拔高了。JAVA語言的設計者就是個物件導向教派的,對物件導向的理論完備性非常執著(Java裡除了幾個基本類型,啥都是繼承Object不是?

高版本如果不是為了向前相容,基本類型也早被包裹類替代了)。

物件導向裡也分流派,上個世紀末,米國幾個大師為能不能多繼承打的頭破血流的,n篇大旗文章,互相看不上。

不過剛才google了一下,已經很難找到了。但後來,“”面向介面編程“”這一概念逐漸被更多人接收。

因為越編寫大型程式,每天要寫代碼的程式員越發現,協議比層次重要太多太多了,哪裡有那麼多父類子類啊,介面本質上是一種協議。

其實JAVA本身的類庫也是越來越多的使用介面了。

舉個最常見的例子: HashTable,原來就是實現了Dictionary這個抽象類別。後來被HashMap代替了

而HashMap對應原來的功能是實現Map介面來完成的(當然了,想線程同步可以用ConcurentHashMap,或者sync一下)。

每種語言都有每種語言的設計思路,其實各有千秋,就拿繼承來說:

其實C++就支援多繼承(這也是java吐槽的),這麼多C++代碼,也沒見出多大亂子給,程式員帶來多大痛苦,python多繼承,也活的好好的,多少人熱愛它。

很多現代語言,比如swift,還有extension這種玩意兒, 動態給一個類或者一個結構體掛個新的方法,也被很多程式員所接受。

Java 不支援多繼承,還有專門阻止繼承的 sealed 關鍵詞存在,但也有很多擁躉。

語言設計的哲學不同,出來的語言就差很多,而這些差異又都是深入思考的結果。

活下來的流行語言,必然有它的獨到之處。

java中抽象類別和介面的區別?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.