interface 和 abstract 的區別
在程式語言中,abstract class和interface是支援抽象類定義的兩種機制。abstract class和interface之間在對於抽象類定義的支援方面具有很大的相似性,甚至可以相互替換,因此很多開發者在進行抽象類定義時對於abstract class和interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區別的,對於它們的選擇甚至反映出對於問題領域本質的理解、對於設計意圖的理解是否正確、合理。
Abstract class |
Interface |
|
例項化 |
不能 |
不能 |
類 |
一種繼承關係,一個類只能使用一次繼承關係。可以通過繼承多個介面實現多重繼承 |
一個類可以實現多個interface |
資料成員 |
可有自己的 |
靜態的不能被修改即必須是static final,一般不在此定義 |
方法 |
可以私有的,非abstract方法,必須實現 |
不可有私有的,預設是public,abstract 型別 |
變數 |
可有私有的,預設是friendly 型,其值可以在子類中重新定義,也可以重新賦值 |
不可有私有的,預設是public static final 型,且必須給其初值,實現類中不能重新定義,不能改變其值。 |
設計理念 |
表示的是“is-a”關係 |
表示的是“like-a”關係 |
實現 |
需要繼承,要用extends |
要用implements |
abstract class和interface在程式語言中都是用來進行抽象類(本文中的抽象類並非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為程式語言中用於定義抽象類的一種方法)定義的,那麼什麼是抽象類,使用抽象類能為我們帶來什麼好處呢?
宣告方法的存在而不去實現它的類被叫做抽象類(abstract class),它用於要建立一個體現某些基本行為的類,併為該類宣告方法,但不能在該類中實現該類的情況。不能建立abstract 類的例項。然而可以建立一個變數,其型別是一個抽象類,並讓它指向具體子類的一個例項。不能有抽象建構函式或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。
介面(interface)是抽象類的變體。在介面中,所有方法都是抽象的。多繼承性可通過實現 這樣的介面而獲得。介面中的所有方法都是抽象的,沒有一個有程式體。介面只可以定義static final成員變數。介面的實現與子類相似,除了該實現類不能從介面定義中繼承行為。當類實現特殊介面時,它定義(即將程式體給予)所有這種介面的方法。 然後,它可以在實現了該介面的類的任何物件上呼叫介面的方法。由於有抽象類,它允許使用介面名作為引用變數的型別。通常的動態聯編將生效。引用可以轉換到 介面型別或從介面型別轉換,instanceof 運算子可以用來決定某物件的類是否實現了介面。
介面可以繼承介面。抽象類可以實現(implements)介面,抽象類是可以繼承實體類,但前提是實體類必須有明確的建構函式。介面更關注“能實現什麼功能”,而不管“怎麼實現的”。
1.相同點 A. 兩者都是抽象類,都不能例項化。 B. interface實現類及abstrct class的子類都必須要實現已經宣告的抽象方法。
2. 不同點 A. interface需要實現,要用implements,而abstract class需要繼承,要用extends。 B. 一個類可以實現多個interface,但一個類只能繼承一個abstract class。 C. interface強調特定功能的實現,而abstract class強調所屬關係。 D. 儘管interface實現類及abstrct class的子類都必須要實現相應的抽象方法,但實現的形式不同。interface中的每一個方法都是抽象方法,都只是宣告的 (declaration, 沒有方法體),實現類必須要實現。而abstract class的子類可以有選擇地實現。 這個選擇有兩點含義: 一是Abastract class中並非所有的方法都是抽象的,只有那些冠有abstract的方法才是抽象的,子類必須實現。那些沒有abstract的方法,在Abstrct class中必須定義方法體。 二是abstract class的子類在繼承它時,對非抽象方法既可以直接繼承,也可以覆蓋;而對抽象方法,可以選擇實現,也可以通過再次宣告其方法為抽象的方式,無需實現,留給其子類來實現,但此類必須也宣告為抽象類。既是抽象類,當然也不能例項化。 E. abstract class是interface與Class的中介。 interface是完全抽象的,只能宣告方法,而且只能宣告pulic的方法,不能宣告private及protected的方法,不能定義方法體,也 不能宣告例項變數。然而,interface卻可以宣告常量變數,並且在JDK中不難找出這種例子。但將常量變數放在interface中違背了其作為接 口的作用而存在的宗旨,也混淆了interface與類的不同價值。如果的確需要,可以將其放在相應的abstract class或Class中。 abstract class在interface及Class中起到了承上啟下的作用。一方面,abstract class是抽象的,可以宣告抽象方法,以規範子類必須實現的功能;另一方面,它又可以定義預設的方法體,供子類直接使用或覆蓋。另外,它還可以定義自己 的例項變數,以供子類通過繼承來使用。
3. interface的應用場合 A. 類與類之前需要特定的介面進行協調,而不在乎其如何實現。 B. 作為能夠實現特定功能的標識存在,也可以是什麼介面方法都沒有的純粹標識。 C. 需要將一組類視為單一的類,而呼叫者只通過介面來與這組類發生聯絡。 D. 需要實現特定的多項功能,而這些功能之間可能完全沒有任何聯絡。
4. abstract class的應用場合 一句話,在既需要統一的介面,又需要例項變數或預設的方法的情況下,就可以使用它。最常見的有: A. 定義了一組介面,但又不想強迫每個實現類都必須實現所有的介面。可以用abstract class定義一組方法體,甚至可以是空方法體,然後由子類選擇自己所感興趣的方法來覆蓋。 B. 某些場合下,只靠純粹的介面不能滿足類與類之間的協調,還必需類中表示狀態的變數來區別不同的關係。abstract的中介作用可以很好地滿足這一點。 C. 規範了一組相互協調的方法,其中一些方法是共同的,與狀態無關的,可以共享的,無需子類分別實現;而另一些方法卻需要各個子類根據自己特定的狀態來實現特定的功能。