什麼是?
它是一套標准,是一套規則,是一套對所有類的統一的要求。
做什麼?
它是為了實現多繼承而出現的。
有什麼?
它只包含兩種成份:
1) 公共的靜態的常量。
2) 抽象方法。
如何做?
通過 interface 關鍵字來實現 。
格式:
public interface 接口名 { ..... }
已知的:
1) 現存的接口(由專家提供)。
2) 自定義的接口(由程序員自己編寫)。
int obj1.compareTo(obj2 )
規定: 對象比較大小必須使用compareTo 作為方法名, 比較大小後的結果必須是一個int型整數。
且當這個整數大於零時,則表示前者大於後者;
當這個整數小於零時,則表示前者小於後者;
當這個整數等於零時,則表示前者與後者相等。
然而,這兩個對象按什麼屬性比較,當前無法確定。因此,這個方法就必須是抽象的。
因此,這個方法如下:
public abstract intcompareTo( Object obj );
此方法為抽象的。根據所學知識可知:抽象方法要麼在抽象類中,要麼在接口中。
試想: 當以上 compareTo()方法置於抽象類中時,則問: 所有類是否均可以與這個抽象類發生繼承關系?
答案: 否定的。
當以上 compareTo()方法置於接口中,則問: 所有類是否可以與這個接口發生繼承(實現)關系?
答案: 肯定的。
由於對象比較大小的規則可以提前制定,因此,專家就為程序員提前准備了一個接口 java.lang.Comparable,其中
存放了 以上抽象方法[ int compareTo(Object obj ) ]
如何實現接口?
通過關鍵字 implements 關鍵字來實現
格式為:
public class 類 implements 接口1 { ...... }
格式為:
public class 類 implements 接口1, 接口2, ... { ...... }
注意: 在Java中,一個類可以不實現接口,也可只實現一個接口, 還可以實現多個接口.
注意: 當一個類實現了接口時,則這個類必須重寫來自接口的所有抽象方法。否則,這個類就是抽象類。
編寫一個類去實現給定的接口。同時,在這個類中重寫來自接口的所有抽象方法。
最後,由此類去創建對象,調用對象的方法來解決業務。完成。
1) 導入 import 包.接口名; 如: import java.lang.Comparable;
2) 編寫類去實現這個接口; 如: public class Student implementsComparable { ...... };
3) 在這個類中重寫來自接口的抽象方法; 如: 重寫 compareTo()方法;
4) 應用(編寫應用程序)。
Demo //學生類 packagecom.hqg.oop.d39; //1導入 接口 importjava.lang.Comparable; importcom.hqg.oop.d38.a2.MyDate; public classStudent extends Object implementsComparable { //2 實現接口 //3 重寫來自接口的所有抽象方法: 目的是讓當前類的對象擁有比較大小的能力。 @Override public int compareTo(Object obj) { Student st2 = (Student)obj; if( this.score > st2.score ){ return 1; }else if( this.score0 ){ //交換 Student tem =stu[j]; stu[j] =stu[j+1]; stu[j+1] =tem; } } } } }
所謂抽象類是用來表征我們在對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象;所謂接口,相當於電源插座,可插入構件相當於電器。可插入構件的關鍵在於存在一個公用的接口,以及每個構件都實現了這個接口。接口是實現構件的可插入性的關鍵。
(1)從語法層來講,Java語言對於抽象類和接口給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。
Demo抽象類的定義方式如下:
abstract classDemo { abstract voidmethod1(); abstract void method2(); … }
Demo的接口定義方式如下:
interface Demo { void method1(); void method2(); … }
在抽象類的定義中,Demo可以有自己的數據成員,也可以有非abstract的成員方法,而在接口的定義中,Demo只能夠有static final數據成員,所有的成員方法都是abstract的。從某種意義上說,接口是一種特殊形式的抽象類。
從編程的角度來看,首先,抽象類和接口的繼承規則不同,抽象只允許單繼承,而一個類卻可以實現多個接口。接口對於多重繼承的支持方面的一種折中考慮;其次,在抽象類的定義中,可以賦予方法的默認行為,而在接口的定義中,方法不能擁有默認行為,必須使用委托,從某種意義上來說,接口比抽象類更為抽象化。
(2)從設計層來講,抽象類在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"Is-A"關系,即父類和子類在概念本質上應該是相同的。對於接口來說則不然,接口並不要求實現者和接口定義在概念本質上是一致的,僅僅是實現了接口定義的契約而已。考慮這樣一個例子,假設在有一個關於Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過抽象類或者接口來定義一個表示該抽象概念的類型,定義方式分別如下所示:
Door抽象類的定義方式如下:
abstract classDoor { abstract voidopen(); abstract voidclose(); }
Door的接口定義方式如下:
interface Door { void open(); void close(); }
其他具體的Door類型可以extends使用抽象類方式定義的Door或者implements使用接口方式定義的Door。看起來好像使用抽象類和接口沒有大的區別。如果現在要求Door還要具有報警的功能。下面將羅列出可能的解決方案,並從設計層對方案進行分析。
解決方案一:
簡單的在Door的定義中增加一個alarm方法,如下:
abstract classDoor { abstract voidopen(); abstract voidclose(); abstract voidalarm(); }
或者
interface Door { void open(); void close(); void alarm(); }
那麼具有報警功能的AlarmDoor的定義方式如下:
class AlarmDoorextends Door { void open(){…} void close(){…} void alarm(){…} }
或者
class AlarmDoorimplements Door{ void open(){…} void close(){…} void alarm(){…} }
這種方法違反了接口隔離原則,在Door的定義中把Door概念本身固有的行為方法和另外一個概念“報警器”的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴於Door這個概念的模塊會因為“報警器”這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。
解決方案二:
既然open、close和alarm屬於兩個不同的概念,根據接口隔離原則應該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用抽象類方式定義;兩個概念都使用接口方式定義;一個概念使用抽象類方式定義,另一個概念使用接口方式定義。
顯然,由於Java語言不支持多重繼承,所以兩個概念都使用抽象類方式定義是不可行的。後面兩種方式都是可行的,但是對於它們的選擇卻反映出對於問題領域中的概念本質的理解、對於設計意圖的反映是否正確、合理。
如果兩個概念都使用接口方式來定義,那麼就反映出兩個問題:第一,我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上 到底是Door還是報警器?第二,如果我們對於問題領域的理解沒有問題,比如:我們通過對於問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那麼我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用接口方式定義)反映不出上述含義。
如果我們對於問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,抽象類在Java語言中表示一種繼承關系,而繼承關系在本質上是"Is-A"關系。所以對於Door這個概念,我們應該使用抽象類方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過接口方式定義。如下所示:
abstract classDoor{ abstract voidopen(); abstract voidclose(); } interface Alarm{ void alarm(); } class AlarmDoorextends Door implements Alarm{ void open(){…} void close(){…} void alarm(){…} }
這種實現方式基本上能夠明確的反映出我們對於問題領域的理解,正確的揭示我們的設計意圖。其實抽象類表示的是"Is-A"關系,interface表示的是"Has-A"關系,在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有 Door的功能,那麼上述的定義方式就要反過來了。
抽象類和接口是Java語言中的兩種定義抽象類的方式,它們之間有很大的相似性。但是對於它們的選擇卻又往往反映出對於問題領域中的概念本質的理解、對於設計意圖的反映是否正確、合理,因為它們表現了概念間的不同的關系。只有正確理解面向對象的設計原則並靈活使用抽象類和接口,才能設計出易用的系統。
接口的出現大大的方便了我們變編程人員的工作,多繼承現象也可以順利解決。其實,接口孕育於生活,稍一體會,就感覺到生活中接口的重要性呢,於編程亦如此。