Java中抽象類(lèi)與接口的區(qū)別
抽象類(lèi)和接口是Java語(yǔ)言中對(duì)于抽象類(lèi)定義進(jìn)行支持的兩種機(jī)制,正是由于這兩種機(jī)制的存在,才賦予了Java強(qiáng)大的面向?qū)ο竽芰?。抽象?lèi)和接口之間在對(duì)于抽象類(lèi)定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開(kāi)發(fā)者在進(jìn)行抽象類(lèi)定義時(shí)對(duì)于抽象類(lèi)和接口的選擇顯得比較隨意。其實(shí),兩者之間還是有很大的區(qū)別的,那么它們之間有什么區(qū)別呢?下面,學(xué)習(xí)啦小編帶你去了解一下。
一、抽象類(lèi)與接口語(yǔ)法定義的區(qū)別
在語(yǔ)法層面,Java語(yǔ)言對(duì)于抽象類(lèi)和接口給出了不同的定義方式,下面以定義一個(gè)名為Demo的抽象類(lèi)為例來(lái)說(shuō)明這種不同。
使用抽象類(lèi)的方式定義Demo抽象類(lèi)的方式如下:
abstract class Demo {
abstract void method1();
abstract void method2();
…
?。?/p>
使用interface的方式定義Demo抽象類(lèi)的方式如下:
interface Demo {
void method1();
void method2();
…
}
在抽象類(lèi)方式中,Demo可以有自己的數(shù)據(jù)成員,也可以有非abstarct的成員方法。
而在接口方式的實(shí)現(xiàn)中,Demo只能夠有靜態(tài)的不能被修改的數(shù)據(jù)成員(也就是必須是static final的,不過(guò)在interface中一般不定義數(shù)據(jù)成員),所有的成員方法都是abstract的。
從某種意義上說(shuō),接口是一種特殊形式的抽象類(lèi)。
二、抽象類(lèi)和接口的編程區(qū)別
從編程的角度來(lái)看,抽象類(lèi)和接口都可以用來(lái)實(shí)現(xiàn)"design by contract"的思想。但是在具體的使用上面還是有一些區(qū)別的。
1、抽象類(lèi)在Java語(yǔ)言中表示的是一種繼承關(guān)系,一個(gè)類(lèi)只能使用一次繼承關(guān)系。
但是,一個(gè)類(lèi)卻可以實(shí)現(xiàn)多個(gè)接口。也許,這是Java語(yǔ)言的設(shè)計(jì)者在考慮Java對(duì)于多重繼承的支持方面的一種折中考慮吧。
2、在抽象類(lèi)的定義中,我們可以賦予方法的默認(rèn)行為。
但是在接口的定義中,方法卻不能擁有默認(rèn)行為,為了繞過(guò)這個(gè)限制,必須使用委托,但是這會(huì) 增加一些復(fù)雜性,有時(shí)會(huì)造成很大的麻煩。
3.在抽象類(lèi)中定義默認(rèn)行為,一旦抽象類(lèi)中的行為方法發(fā)生改變,就會(huì)影響繼承他的子類(lèi)。
但是另一個(gè)方面,如果不利用抽象類(lèi)中定義默認(rèn)行為,就會(huì)導(dǎo)致同樣的方法實(shí)現(xiàn)出現(xiàn)在該抽象類(lèi)的每一個(gè)派生類(lèi)中,違反了"one rule,one place"原則,造成代碼重復(fù),同樣不利于以后的維護(hù)。
因此,在抽象類(lèi)和接口間進(jìn)行選擇時(shí)要非常的小心。
三、抽象類(lèi)和接口的設(shè)計(jì)理念區(qū)別
上面主要從語(yǔ)法定義和編程的角度論述了抽象類(lèi)和接口的區(qū)別,這些層面的區(qū)別是比較低層次的、非本質(zhì)的。現(xiàn)在小編將從另一個(gè)層面,即抽象類(lèi)和接口所反映出的設(shè)計(jì)理念,來(lái)分析一下二者的區(qū)別。小編認(rèn)為,從這個(gè)層面進(jìn)行分析才能理解二者概念的本質(zhì)所在。
抽象類(lèi)在Java語(yǔ)言中體現(xiàn)了一種繼承關(guān)系,要想使得繼承關(guān)系合理,父類(lèi)和派生類(lèi)之間必須存在"is a"關(guān)系,即父類(lèi)和派生類(lèi)在概念本質(zhì)上應(yīng)該是相同的(參考文獻(xiàn)〔3〕中有關(guān)于"is a"關(guān)系的大篇幅深入的論述,有興趣的讀者可以參考)。
對(duì)于接口來(lái)說(shuō)則不然,并不要求接口的實(shí)現(xiàn)者和接口定義在概念本質(zhì)上是一致的,僅僅是實(shí)現(xiàn)了接口定義的契約而已。為了使論述便于理解,下面將通過(guò)一個(gè)簡(jiǎn)單的實(shí)例進(jìn)行說(shuō)明。
考慮這樣一個(gè)例子,假設(shè)在我們的問(wèn)題領(lǐng)域中有一個(gè)關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個(gè)動(dòng)作open和close,此時(shí)我們可以通過(guò)抽象類(lèi)或者接口來(lái)定義一個(gè)表示該抽象概念的類(lèi)型,定義方式分別如下所示:
使用抽象類(lèi)方式定義Door:
abstract class Door {
abstract void open();
abstract void close();
}
使用接口方式定義Door:
interface Door {
void open();
void close();
}
其他具體的Door類(lèi)型可以extends使用抽象類(lèi)方式定義的Door或者implements使用接口方式定義的Door??雌饋?lái)好像使用抽象類(lèi)和接口沒(méi)有大的區(qū)別。