java中 抽象類和接口的區別

一. 什麼是抽象類及什麼是抽象方法
抽象方法是一種特殊的方法:他只有聲明,而沒有具體實現,抽象方法的聲明格式爲:
abstract void funName();
抽象方法必須用 abstract 修飾。若是一個類含有抽象方法,則稱這個類爲抽象類,抽象類必須在類前使用 abstract 關鍵字進行修飾。
由於抽象類中含有沒有具體實現的抽象方法,因此不能用來實例化對象,只能被繼承。抽象類不必定含有抽象方法(即便沒有抽象方法,類也能夠用abstrct修飾成爲抽象類,可是這麼作毫無心義),可是含有抽象方法的類必定是抽象類。
抽象類的定義爲:
public abstract class ClassName{ abstract void funName(); }函數

抽象類就是爲了被繼承才存在的,對於一個父類,若是它的某個方法在父類中實現出來沒有任何意義,必須根據子類的實際需求來進行不一樣的實現,那麼就能夠將這個方法聲明爲abstract方法,此時這個類也就成爲abstract類了。
包含抽象方法的類稱爲抽象類,但並不意味着抽象類中只能有抽象方法,它和普通類同樣,一樣能夠擁有成員變量和普通的成員方法。注意,抽象類和普通類的主要有三點區別:
1)抽象方法必須爲public或者protected(由於若是爲private,則不能被子類繼承,子類便沒法實現該方法),缺省狀況下默認爲public。
2)抽象類不能用來建立對象;
3)若是一個類繼承於一個抽象類,則子類必須實現父類的抽象方法。若是子類沒有實現父類的抽象方法,則必須將子類也定義爲爲abstract類。
在其餘方面,抽象類和普通的類並無區別。
二.什麼是接口
接口,英文稱做interface,在軟件工程中,接口泛指供別人調用的方法或者函數。從這裏,咱們能夠體會到Java語言設計者的初衷,它是對行爲的抽象。在Java中,定一個接口的形式以下:
`[public] interface InterfaceName {設計

}`

接口中能夠含有 變量和方法。可是要注意,接口中的變量會被隱式地指定爲public static final變量(而且只能是public static final變量,用private修飾會報編譯錯誤),而方法會被隱式地指定爲public abstract方法且只能是public abstract方法(用其餘關鍵字,好比
private、protected、static、 final等修飾會報編譯錯誤),而且接口中全部的方法不能有具體的實現,也就是說,接口中的方法必須都是抽象方法。從這裏能夠隱約看出接口和抽象類的區別,接口是一種極度抽象的類型,它比抽象類更加「抽象」,而且通常狀況下不在接
口中定義變量。
要讓一個類遵循某組特意的接口須要使用implements關鍵字,具體格式以下:
`class ClassName implements Interface1,Interface2,[....]{code

}`

能夠看出,容許一個類遵循多個特定的接口。若是一個非抽象類遵循了某個接口,就必須實現該接口中的全部方法。對於遵循某個接口的抽象類,能夠不實現該接口中的抽象方法。
三.接口和抽象類的區別:
1.語法層面上的區別
1)抽象類能夠提供成員方法的實現細節,而接口中只能存在public abstract 方法;
2)抽象類中的成員變量能夠是各類類型的,而接口中的成員變量只能是public static final類型的;
3)接口中不能含有靜態代碼塊以及靜態方法,而抽象類能夠有靜態代碼塊和靜態方法;
4)一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。
2.設計層面上的區別
1)抽象類是對一種事物的抽象,即對類抽象,而接口是對行爲的抽象。抽象類是對整個類總體進行抽象,包括屬性、行爲,可是接口倒是對類局部(行爲)進行抽象。舉個簡單的例子,飛機和鳥是不一樣類的事物,可是它們都有一個共性,就是都會飛。那麼在設計的時候,能夠將飛機設計爲一個類Airplane,將鳥設計爲一個類Bird,可是不能將 飛行 這個特性也設計爲類,所以它只是一個行爲特性,並非對一類事物的抽象描述。此時能夠將 飛行 設計爲一個接口Fly,包含方法fly( ),而後Airplane和Bird分別根據本身的須要實現Fly這個接口。而後至於有不一樣種類的飛機,好比戰鬥機、民用飛機等直接繼承Airplane便可,對於鳥也是相似的,不一樣種類的鳥直接繼承Bird類便可。從這裏能夠看出,繼承是一個 "是否是"的關係,而 接口 實現則是 "有沒有"的關係。若是一個類繼承了某個抽象類,則子類一定是抽象類的種類,而接口實現則是有沒有、具有不具有的關係,好比鳥是否能飛(或者是否具有飛行這個特色),能飛行則能夠實現這個接口,不能飛行就不實現這個接口。
2)設計層面不一樣,抽象類做爲不少子類的父類,它是一種模板式設計。而接口是一種行爲規範,它是一種輻射式設計。什麼是模板式設計?最簡單例子,你們都用過ppt裏面的模板,若是用模板A設計了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,若是它們的公共部分須要改動,則只須要改動模板A就能夠了,不須要從新對ppt B和ppt C進行改動。而輻射式設計,好比某個電梯都裝了某種報警器,一旦要更新報警器,就必須所有更新。也就是說對於抽象類,若是須要添加新的方法,能夠直接在抽象類中添加具體的實現,子類能夠不進行變動;而對於接口則不行,若是接口進行了變動,則全部實現這個接口的類都必須進行相應的改動。
下面看一個網上流傳最普遍的例子:門和警報的例子:門都有open( )和close( )兩個動做,此時咱們能夠定義經過抽象類和接口來定義這個抽象概念:
abstract class Door { public abstract void open(); public abstract void close(); }
或者
interface Door { public abstract void open(); public abstract void close(); }
可是如今若是咱們須要門具備報警alarm( )的功能,那麼該如何實現?下面提供兩種思路:
1)將這三個功能都放在抽象類裏面,可是這樣一來全部繼承於這個抽象類的子類都具有了報警功能,可是有的門並不必定具有報警功能;
2)將這三個功能都放在接口裏面,須要用到報警功能的類就須要實現這個接口中的open( )和close( ),也許這個類根本就不具有open( )和close( )這兩個功能,好比火災報警器。
從這裏能夠看出, Door的open() 、close()和alarm()根本就屬於兩個不一樣範疇內的行爲,open()和close()屬於門自己固有的行爲特性,而alarm()屬於延伸的附加行爲。所以最好的解決辦法是單獨將報警設計爲一個接口,包含alarm()行爲,Door設計爲單獨的一個抽象類,包含open和close兩種行爲。再設計一個報警門繼承Door類和實現Alarm接口。
interface Alram { void alarm(); }對象

`abstract class Door {
    void open();
    void close();
    }`

 `class AlarmDoor extends Door implements Alarm {
    void oepn() {
      //....
    }
     void close() {
      //....
    }
    void alarm() {
      //....
    }
}`

參考:http://www.cnblogs.com/dolphin0520/blog

相關文章
相關標籤/搜索