abstract class和interface是Java語言中對于抽象類定義進行支持的兩種機制抬旺,正是由于這兩種機制的存在,才賦予了Java強大的面向對象能力疹吃。
抽象類:
所有的對象都是通過類來描繪的仔粥,但是反過來卻不是這樣筹误。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象逊笆,這樣的類就是抽象類栈戳。
抽象類是是用來捕捉子類的通用特性的,是一種模板难裆,它不能被實例化子檀,只能被用作子類的超類。抽象類必須在類前用abstract關鍵字修飾乃戈。抽象類不能實例
只要包含一個抽象方法的類褂痰,該類必須要定義成抽象類
抽象類的目的:
1,? 抽象類就是為了繼承而存在的偏化,為子類提供一個公共的類型脐恩;
2,? 封裝子類中的重復內容(成員變量和方法)侦讨;
3驶冒,? 定義抽象方法,子類雖然有不同的實現(xiàn)韵卤,但該方法的定義是一致的骗污。
抽象類中包含抽象方法,抽象方法的聲明格式為:
public?abstract?void?cry();
抽象方法是一種特殊的方法:它只有聲明沈条,而沒有具體的實現(xiàn)
抽象類例子:
public?abstract?class?Animal?{
public?abstract?void?cry();
}
子類繼承例子:
public?class?Dog?extends?Animal{
@Override
public?void?cry()?{
System.out.println("狗叫...");
}
}
抽象類中不只有抽象方法需忿,它和普通類一樣,同樣可以擁有成員變量和普通的成員方法蜡歹。注意屋厘,抽象類和普通類的主要有三點區(qū)別:
1)抽象方法必須為public或者protected(因為如果為private,則不能被子類繼承月而,子類便無法實現(xiàn)該方法)汗洒,缺省情況下默認為public。
2)抽象類不能用來創(chuàng)建對象(不能被實例)父款;因為抽象類中含有無具體實現(xiàn)的方法
3)如果一個類繼承于一個抽象類溢谤,則子類必須實現(xiàn)父類的抽象方法瞻凤。如果子類沒有實現(xiàn)父類的抽象方法,則必須將子類也定義為為abstract類世杀。(抽象類可以繼承抽象類)
接口(interface):
接口泛指供別人調用的方法或者函數(shù)阀参,它是對行為的抽象。接口是抽象的抽象瞻坝。
接口是抽象方法的集合蛛壳,是一種形式,一種標準湿镀,就像契約模式炕吸,如果實現(xiàn)了這個接口,那么就必須確保使用這些方法勉痴。接口中的方法必須都是抽象方法赫模,并且接口中所有的方法不能有具體的實現(xiàn),接口中成員變量只能是public static final這種形式蒸矛,相當于常量瀑罗,不可以修改的(一般不在接口中定義成員變量)
方法只能為public,當然你可以顯示的聲明為protected雏掠、private斩祭,但是編譯會出錯
注意點:實現(xiàn)類必須要實現(xiàn)該接口的所有方法
接口的使用,需要使用implements關鍵字乡话,具體格式如下:
class ClassName implementsInterface1,Interface2,[....]{
}
接口的例子:
interface?Door{
void?open ();
void?close();
}
子類中實現(xiàn)接口:
Public class BigDoor implements Door {
void?open (){
//實現(xiàn)
};
void?close(){
//實現(xiàn)
};
}
抽象類與接口的區(qū)別:
一摧玫、語法層面上的區(qū)別:
1.??????抽象類可以多種修飾方法,接口中只能存在public abstract 方法
2.??????一個類只能繼承一個抽象類绑青,而一個類卻可以實現(xiàn)多個接口
二诬像、設計層面上的區(qū)別
1)抽象類是對一種事物的抽象,即對類抽象闸婴,而接口是對行為的抽象坏挠。抽象類是對整個類整體進行抽象,包括屬性邪乍、行為降狠,但是接口卻是對類局部(行為)進行抽象。舉個簡單的例子庇楞,飛機和鳥是不同類的事物榜配,但是它們都有一個共性,就是都會飛吕晌。那么在設計的時候芥牌,可以將飛機設計為一個類Airplane,將鳥設計為一個類Bird聂使,但是不能將飛行 這個特性也設計為類壁拉,因此它只是一個行為特性,并不是對一類事物的抽象描述柏靶。此時可以將飛行 設計為一個接口Fly弃理,包含方法fly( ),然后Airplane和Bird分別根據(jù)自己的需要實現(xiàn)Fly這個接口屎蜓。然后至于有不同種類的飛機痘昌,比如戰(zhàn)斗機、民用飛機等直接繼承Airplane 即可炬转,對于鳥也是類似的辆苔,不同種類的鳥直接繼承Bird類即可。
從這里可以看出扼劈,繼承是一個 "是不是"的關系驻啤,而 接口 實現(xiàn)則是 "有沒有"的關系。如果一個類繼承了某個抽象類荐吵,則子類必定是抽象類的種類骑冗,而接口實現(xiàn)則是有沒有、具備不具備的關系先煎,比如鳥是否能飛(或者是否具備飛行這個特點)贼涩,能飛行則可以實現(xiàn)這個接口,不能飛行就不實現(xiàn)這個接口薯蝎。
2)設計層面不同遥倦,抽象類作為很多子類的父類,它是一種模板式設計占锯。而接口是一種行為規(guī)范袒哥,它是一種輻射式設計。什么是模板式設計烟央?最簡單例子统诺,大家都用過ppt里面的模板,如果用模板A設計了ppt B和ppt C疑俭,ppt B和ppt C公共的部分就是模板A了粮呢,如果它們的公共部分需要改動,則只需要改動模板A就可以了钞艇,不需要重新對ppt B和ppt C進行改動啄寡。而輻射式設計,比如某個電梯都裝了某種報警器哩照,一旦要更新報警器挺物,就必須全部更新。也就是說對于抽象類飘弧,如果需要添加新的方法识藤,可以直接在抽象類中添加具體的實現(xiàn)砚著,子類可以不進行變更;而對于接口則不行痴昧,如果接口進行了變更稽穆,則所有實現(xiàn)這個接口的類都必須進行相應的改動。
下面看一個最廣泛的例子:門和警報的例子:門都有open( )和close( )兩個動作赶撰,此時我們可以定義通過抽象類和接口來定義這個抽象概念:
abstract class Door {
public abstract void open();
public abstract void close();
}
或者:
interface Door {
public abstract void open();
public abstract void close();
}
但是現(xiàn)在如果我們需要門具有報警alarm( )的功能舌镶,那么該如何實現(xiàn)?下面提供兩種思路:
1)將這三個功能都放在抽象類里面豪娜,但是這樣一來所有繼承于這個抽象類的子類都具備了報警功能餐胀,但是有的門并不一定具備報警功能;
2)將這三個功能都放在接口里面瘤载,需要用到報警功能的類就需要實現(xiàn)這個接口中的open( )和close( )否灾,也許這個類根本就不具備open( )和close( )這兩個功能,比如火災報警器惕虑。
從這里可以看出坟冲,?Door的open() 、close()和alarm()根本就屬于兩個不同范疇內的行為溃蔫,open()和close()屬于門本身固有的行為特性健提,而alarm()屬于延伸的附加行為。因此最好的解決辦法是單獨將報警設計為一個接口伟叛,包含alarm()行為,Door設計為單獨的一個抽象類私痹,包含open和close兩種行為。再設計一個報警門繼承Door類和實現(xiàn)Alarm接口统刮。
interface Alram {
void alarm();
}
abstract class Door {
void open();
void close();
}
class AlarmDoor extends Door implements Alarm {
void oepn() {
//....
}
void close() {
//....
}
void alarm() {
//....
}
}
兩者正確使用方式:
宏觀上講:
抽象類表示的是紊遵,這個對象是什么。接口表示的是侥蒙,這個對象能做什么暗膜,具備什么。
抽象類使用:比如鞭衩,男人学搜,女人,這兩個類论衍,他們的抽象類是人瑞佩。說明,他們都是人坯台。
接口使用:比如炬丸,人可以吃東西,貓也可以吃東西蜒蕾,你可以把“吃東西”定義成一個接口稠炬,然后讓這些類去實現(xiàn)它.
當你關注一個事物的本質的時候焕阿,用抽象類;當你關注一個操作的時候酸纲,用接口捣鲸。
具體注意點:
1、如果你擁有一些方法并且想讓它們中的一些有默認實現(xiàn)闽坡,那么使用抽象類吧。
2愁溜、如果你想實現(xiàn)多重繼承疾嗅,那么你必須使用接口。由于Java不支持多繼承冕象,子類不能夠繼承多個類代承,但可以實現(xiàn)多個接口。因此你就可以使用接口來解決它渐扮。
3论悴、如果基本功能在不斷改變,那么就需要使用抽象類墓律。如果不斷改變基本功能并且使用接口膀估,那么就需要改變所有實現(xiàn)了該接口的類。
ISP(Interface Segregation Principle)接口隔離原則(面向對象的一個核心原則):
1耻讽、? 它表明使用多個專門的接口比使用單一的總接口要好察纯。
2、? 一個類對另外一個類的依賴性應當是建立在最小的接口上的针肥。
3饼记、? ?一個接口代表一個角色,不應當將不同的角色都交給一個接口慰枕。沒有關系的接口合并在一起具则,形成一個臃腫的大接口,這是對角色和接口的污染具帮。
總結:
1博肋、一個類只能繼承一個抽象類,但是可以實現(xiàn)多個接口匕坯。
2束昵、 在抽象類中可以擁有自己的成員變量和非抽象類方法,但是接口中只能存在靜態(tài)的不可變的成員數(shù)據(jù)(不過一般都不在接口中定義成員數(shù)據(jù))葛峻,而且它的所有方法都是抽象的锹雏。
接口是公開的,里面不能有私有的方法或變量术奖,是用于讓別人使用的礁遵,而抽象類是可以有私有方法或私有變量的
3轻绞、抽象類和接口所反映的設計理念是不同的,抽象類所代表的是“is-a”的關系佣耐,而接口所代表的是“has-a”的關系政勃。
4、實現(xiàn)接口的一定要實現(xiàn)接口里定義的所有方法兼砖,而實現(xiàn)抽象類可以有選擇地重寫需要用到的方法奸远,一般的應用里,最頂級的是接口讽挟,然后是抽象類實現(xiàn)接口懒叛,最后才到具體類實現(xiàn)。