引用:
深入理解Java的接口和抽象類-https://www.cnblogs.com/dolphin0520/p/3811437.html
接口和抽象類的區別-https://www.cnblogs.com/east7/p/10580245.html
在面向對象的變成來說,抽象其一大特性,可以通過兩種形式體現OOP的抽象:抽象類和接口。而兩者雖然都體現了OOP的抽象,但其目的,特性是有所不同的,如下例:
如果飛機
繼承交通工具類
,挖掘機
繼承製造工具類
,飛機
和挖掘機
想使用同樣的加油方法
那麼是沒有辦法通過繼承實現的,因爲類的繼承是單繼承。
如果將加油行爲
定義成是接口加油站
,那麼飛機
和挖掘機
想使用同樣的加油方法
就很簡單了。寫一個接口讓飛機
和挖掘機
實現這個接口就可以瞭如下圖:
一、抽象類
含有abstract修飾符的類即爲抽象類,抽象類是爲了繼承而存在。
public abstract class Transport {
abstract void drive();
public void maintain() {
System.out.println("保養維護");
}
}
特點:
- 抽象類不能實例化,只能通過繼承使用;
- 在抽象類中,可以定義普通變量,普通方法/抽象方法,但是定義的抽象方法必須在具體子類中實現。
public class AirPlane extends Transport{
@Override
void drive() {
System.out.println("dirve airplane");
}
public void maintain() {
super.maintain();
System.out.println("飛機保養維護");
}
}
- 抽象類中不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
- 構造方法,類方法(用 static 修飾的方法)不能聲明爲抽象方法。
相關概念辨析:
抽象類的子類必須給出抽象類中的抽象方法的具體實現,除非該子類也是抽象類。
abstract和final是不能共存的:抽象類需要被繼承才能使用,而被final修飾的類無法被繼承。
可以通過訪問修飾符public、protected和default修飾其作用範圍:抽象類除了其抽象的定義外與普通類的使用類似。
抽象類可繼承一個類和實現多個接口。
二、接口
接口,英文稱作interface,在軟件工程中,接口泛指供別人調用的方法或者函數。從這裏,我們可以體會到Java語言設計者的初衷,它是對行爲的抽象。在Java中,定一個接口的形式如下:
[public] interface InterfaceName {
}
接口中的方法必須都是抽象方法,是一種極度抽象的類型,它比抽象類更加“抽象”,並且一般情況下不在接口中定義變量。
接口與類的區別:
- 接口不能用於實例化對象。
- 接口沒有構造方法。
- 接口中所有的方法必須是抽象方法。
- 接口不能包含成員變量,除了 static 和 final 變量。
- 接口不是被類繼承了,而是要被類實現。
- 接口支持多繼承。
接口特性
- 接口中每一個方法也是隱式抽象的,接口中的方法會被隱式的指定爲 public abstract(只能是 public abstract,其他修飾符都會報錯)。
- 接口中可以含有變量,但是接口中的變量會被隱式的指定爲 public static final 變量(並且只能是 public,用 private 修飾會報編譯錯誤)。
- 接口中的方法是不能在接口中實現的,只能由實現接口的類來實現接口中的方法。
三、異同對比
抽象類和接口的區別
1.語法層面上的區別
- 抽象類中的方法可以有方法體,就是能實現方法的具體功能,但是接口中的方法不行。
- 抽象類中的成員變量可以是各種類型的,而接口中的成員變量只能是 public static final 類型的。
- 接口中不能含有靜態代碼塊以及靜態方法(用 static 修飾的方法),而抽象類是可以有靜態代碼塊和靜態方法。
- 一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。
性質 | 抽象類 | 接口 |
---|---|---|
訪問修飾符 | public、protected和default | 只有****public |
多繼承 | 繼承一個類和實現多個接口 | 只可以繼承一個或多個其它接口 |
是否有構造函數 | 是 | 否 |
main方法 | 支持 | 不支持 |
方法實體實現 | 支持 | 不支持,接口完全是抽象的 |
與正常Java類的區別 | 不能實例化抽象類,因爲有abstract方法 | 接口是完全不同的類型 |
使用: | 子類使用extends關鍵字來繼承抽象類,實現所有抽象方法** | 子類使用關鍵字implements來實現接口,需要實現接口中聲明的所有方法 |
速度 | 速度快 | 稍微有點慢,因爲它需要時間去尋找在類中實現的方法 |
添加新方法 | 添加後可以給它提供默認的實現,故不需要改變現在的代碼 | 添加後必須改變實現該接口的類 |
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進行改動。
而輻射式設計,比如某個電梯都裝了某種報警器,一旦要更新報警器,就必須全部更新。
也就是說對於抽象類,如果需要添加新的方法,可以直接在抽象類中添加具體的實現,子類可以不進行變更;而對於接口則不行,如果接口進行了變更,則所有實現這個接口的類都必須進行相應的改動。
什麼時候使用抽象類和接口?
•如果擁有一些方法並且想讓它們中的一些有默認實現,那麼使用抽象類。
•如果想實現多重繼承,那麼必須使用接口。由於Java不支持多繼承,子類不能夠繼承多個類,但可以實現多個接口。因此就可以使用接口來解決它。
•如果基本功能在不斷改變,那麼就需要使用抽象類。如果不斷改變基本功能並且使用接口,那麼就需要改變所有實現了該接口的類。