對于很多開發者來說,抽象類與接口的選擇都很模糊,也有很多開發人員壓根就不使用他們。你或許會說,隻要實作功能就行,我甚至都不适用任何架構都可以寫出來。當然,每個開發人員都是獨立的個體,都有自己獨特的想法,尤其是java程式設計行業。會定義變量,會建立對象,會程式流程等一些基本知識的了解都可以上手開發項目,如果你是這麼認為的,那麼請選擇關閉這篇文章。
1、什麼是抽象類
通俗的将就是這個類是被迫這樣子的,兒子欠别人的錢,老子不能不還呀!因為該類中肯定存在抽象方法,是以我必須是抽象類。如果還跟普通的類一樣的話,我存在的價值就展現不出來了。
有抽象方法的類肯定是抽象類,那麼抽象類中肯定有抽象方法嗎?(當然不是,老子是個窮光蛋,不一定兒子就是個窮光蛋。)
抽象類中除了有特定的抽象方法之外,跟普通類沒有多大的差別,可以有自己的屬性和方法。
public abstract class Car {
/**
* 該方法是一個抽象方法
* 抽象方法隻有定義,沒有實作
* 同樣因為抽象類中有沒有實作的方法,是以抽象類時不可能建立某一個具體的對象的
*/
public abstract void move();
/**
* 可以定義普通的方法
*/
public void open(){
System.out.println("------汽車可以開------");
}
/**
* 也可以定義自己的屬性
*/
private String name;
private int speed;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int speed) {
this.speed = speed;
}
public static void main(String[] args) {
}
}
有的人會問:什麼是抽象方法呢?簡單了解就是,你隻是知道我的名字,卻不知道我具體是幹什麼的。抽象方法是一種特殊的方法:它隻有聲明,而沒有具體的實作。
與普通方法的差別就是,abstract。
因為抽象類中含有沒有實作的抽象方法,是以是不可能new出來對象的,是不可能有自己的對象的。要不又跟普通類一樣。
簡單一句話:就因為有一個沒有實作的方法,所有java才會給這一個特性起名為抽象。這個特殊的方法産生了,我們就要想辦法去管理它,所有就産生了抽象類。抽象類如果可以自己定義對象的話,那跟普通的類不一樣了嗎?是以抽象類它才會産生這個不能定義自己對象的特性。
1)抽象方法必須是public或者protected,因為如果是private子類是不可能去繼承,也會存在實作功能。
2)抽象類不能用來建立對象;
3)如果一個類繼承于一個抽象類,則子類必須實作父類的抽象方法。如果子類沒有實作父類的抽象方法,則必須将子類也定義為為abstract類。
在其他方面,抽象類和普通的類并沒有差別。
2、什麼是接口。
接口,英文稱作interface,在軟體工程中,接口泛指供别人調用的方法或者函數。從這裡,我們可以體會到Java語言設計者的初衷,它是對行為的抽象。
在Java中,定一個接口的形式如下:
接口中可以含有 變量和方法。但是要注意,接口中的變量會被隐式地指定為public static final變量(并且隻能是public static final變量,用private修飾會報編譯錯誤),而方法會被隐式地指定為public abstract方法且隻能是public abstract方法(用其他關鍵字,比如private、protected、static、 final等修飾會報編譯錯誤),并且接口中所有的方法不能有具體的實作,也就是說,接口中的方法必須都是抽象方法。
從這裡可以隐約看出接口和抽象類的差別,接口是一種極度抽象的類型,它比抽象類更加“抽象”,并且一般情況下不在接口中定義變量。
接口是抽象類的抽象。
3、他們兩者之間的差別。
3.1、java文法上面差別;
1)抽象類中的屬性和方法可以是任意類型的,接口中的屬性和方法預設是抽象的。
2)抽象類中的方法包含靜态代碼塊和靜态方法,接口中是不允許的。
3)一個類隻能繼承一個抽象類,而一個類卻可以實作多個接口。
3.2、java設計層面上的差別。
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( )兩個動作,此時我們可以定義通過抽象類和接口來定義這個抽象概念:
1 2 3 4 | |
或者:
1 2 3 4 | |
但是現在如果我們需要門具有報警alarm( )的功能,那麼該如何實作?下面提供兩種思路:
1)将這三個功能都放在抽象類裡面,但是這樣一來所有繼承于這個抽象類的子類都具備了報警功能,但是有的門并不一定具備報警功能;
2)将這三個功能都放在接口裡面,需要用到報警功能的類就需要實作這個接口中的open( )和close( ),也許這個類根本就不具備open( )和close( )這兩個功能,比如火災報警器。
從這裡可以看出, Door的open() 、close()和alarm()根本就屬于兩個不同範疇内的行為,open()和close()屬于門本身固有的行為特性,而alarm()屬于延伸的附加行為。是以最好的解決辦法是單獨将報警設計為一個接口,包含alarm()行為,Door設計為單獨的一個抽象類,包含open和close兩種行為。再設計一個報警門繼承Door類和實作Alarm接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |