8.9.2 接口
接口(Interface)是一種復合數據類型。
至此,Java語言的所有數據類型介紹完了,下面進行一個簡單的總結。Java語言的數據類型分為兩大類:基本數據類型和復合數據類型,其中基本數據類型有8種,復合數據類型包括數組、類和接口,由於開發過程中可以根據需要聲明新的復合數據類型,所以復合數據類型的數量有無限個。
接口的概念,現實中使用的也很多,例如大家經常使用的U盤,則需要和計算機上的USB接口匹配使用,而且USB設備中除了U盤以外還有很多,例如USB風扇、USB數據線、USB鼠標、USB鍵盤等,他們都使用計算機上統一的USB接口,這樣設備的通用性很強。簡化了計算機接口的設計,使計算機不需要具備鼠標接口、鍵盤接口等專用的結構。
廣義上來說,兩個人說不同的方言,互相之間無法聽懂另一方表達的意義,我們也可以稱之為雙方使用的接口不統一,CPU無法和主板匹配,我們也可以稱之為接口不統一,例如AMD和Intel的CPU采用不同的針腳結構,甚至同一廠商不同型號的CPU針腳結構也不統一,這樣很不方便設備之間的匹配,使用專業的技術術語叫作兼容性差。
那麼什麼是接口呢?其實接口就是一套規范。
例如USB接口,分為兩套規范:公接口和母接口。例如U盤、USB鼠標上的USB接口為公接口,而電腦上的USB接口為母接口。規范中只規定公接口有4個通道,那些用來傳輸數據、那些用來進行供電,母接口規范只規定也有4個通道,那些用來傳輸數據,那些用來進行供電,電壓是多少電流多大等。所有的這些規范都只規定了必須實現那些功能,但是卻沒有規定如何進行實現。
這種只規定實現什麼功能,而不限制如何進行實現的結構,在程序設計領域中稱作“設計和實現相分離”,其中規定實現的功能屬於設計部分,而如何實現功能則是實現部分。這樣進行程序項目制作,可以讓一部分人專門進行項目設計,而由另一部分人進行項目實現。這點,很類似汽車的制造,由設計人員設計汽車,由制造人員進行制造。
這種“設計和實現相分離”的結構將極大的簡化程序項目的設計和管理,使得整個項目的分工更加細致,也就是使程序設計完全獨立出來,而在設計完成以後再進行代碼編寫。
接口就是一個純粹用來設計的數據類型,在接口這種數據類型中,只能書寫兩類聲明的結構:
l 常量數據
所有的常量數據都是public static的。如果聲明時不書寫則系統將自動添加這兩個修飾符。
l 抽象方法
接口中的所有方法都只在邏輯上規定該方法的作用,而不能書寫方法體。所有接口中的方法都是public abstract的,如果聲明時不書寫則系統將自動添加這兩個修飾符。
其中接口中的數據是常數,以後不能改變,而方法只是規定要做什麼,而不去規定如何進行實現。這樣接口就很方便設計人員進行設計,而不必過多的關系對應的方法如何在邏輯上進行實現。
接口聲明的語法格式如下:
訪問控制符 interface 接口名 [extends 父接口名1,父接口名2……]{
常量聲明
方法聲明
}
和類的聲明一樣,訪問控制符只能使用public和默認的。聲明時使用interface關鍵字聲明接口,接口可以繼承其它的接口,使用extends關鍵字進行繼承,多個接口名之間使用逗號進行分隔。和類的集成一樣,子接口繼承父接口中所有的常量數據和方法,子接口的對象也是父接口的對象。
注意:和抽象類一樣,接口只能聲明對象,而不能創建對象。
接口聲明的示例代碼如下,例如聲明一個USB接口來代表實際使用中的USB結構:
public interface USB{
/**電壓*/
public static final int V = 5;
/**讀取數據*/
public abstract byte[] readData();
/**寫入數據*/
public abstract void writeData(byte[] data);
}
該接口中規定電壓常量為5V,聲明了兩個方法,要求實現USB時必須實現這樣兩個方法,至於如何實現這裡不做規定。這樣這個數據類型就只是設計上的說明,而不牽扯具體的實現,這樣在項目中使用時則比較通用。
從這點來看,接口類似於現實中使用的各個國家標准,標准中只規定該類型最終需要達到的標准,而不規定如何實現,各個廠商可以根據自己的產品工藝實現該要求即可。
在實際的項目中,設計接口需要對於項目的整體有比較深刻的了解和認識,這樣才可以設計出需要的接口結構,關於接口的設計這裡不作太深入的論述。如果需要更深刻的了解設計的結構,可以參閱OReilly的《Designing.Interfaces》一書。
接口設計完成以後,還需要再項目中實現接口規范中對應的要求,一般聲明對應的類來實現接口,實現接口的語法為:
訪問控制符 [修飾符] class 類名 [extends 父類名] implements 父接口名1,父接口名2……
實現接口的語法位於類聲明中,位於繼承聲明的後面,使用implements關鍵字代表實現,後續是需要實現的接口的名稱,一個類可以實現任意多個接口。
實現接口和繼承類很類似,聲明的類稱作接口的子類,接口為該類的父接口,子類中繼承父接口中所有的數據和方法,因為接口中所有的方法都是抽象方法,所以如果子類中不實現(覆蓋)父接口中的方法,則該類必須聲明為抽象類。
例如計算機實現了USB接口,則示例代碼如下:
public class Computer implements USB{
/**內存容量*/
int memorySize;
public abstract byte[] readData(){
//讀數據的邏輯
}
public abstract void writeData(byte[] data){
//寫數據的邏輯
}
}
這裡,Computer類實現了前面的USB接口,在Computer類內部可以書寫和Computer類相關的屬性、方法和構造方法,這裡對於實現接口沒有影響,而因為實現了USB接口,則必須覆蓋USB接口中的readData和writeData抽象方法,至於方法內部的代碼,則根據邏輯的需要進行實現,從而實現接口中要求實現的功能。
類似的,也可以使一個數碼相機實現USB接口,則實現的示例代碼為:
public class DigitalCamera implements USB{
/**廠商名稱*/
String vendorName;
public abstract byte[] readData(){
//讀數據的邏輯
}
public abstract void writeData(byte[] data){
//寫數據的邏輯
}
}
在該類中,也可以根據該類的需要實現USB接口中規定的功能,至於如何實現則很可能和Computer類不同。
這樣,雖然Computer類和DigitalCamera類自身原來的功能不同,但是都可以通過實現USB接口而實現同樣的功能,這樣單純的從是否支持USB功能來看,這兩個類的實現是一樣的。按照面向對象的術語來說,這被稱作屏蔽了類的類型之間的不同,保證了程序的通用性。
由於實現接口時,不限制實現的接口的數量,則任何一個類都可以實現任意多個接口,這樣就使類的通用性獲得了極大的增強,很方便類的對象之間的匹配。就像現實中USB接口規范方便了多種不同設備之間的互聯一樣。
在語法上,實現了接口的對象可以使用子類的構造方法進行創建,這樣又很適合多態的結構,可以說接口的出現,使多態的特性更容易的進行實現。
在實際項目中,通過使用一定的接口,使得很多類的對象在實現某種類型的功能時,方法的聲明是統一的,便於程序的調用和管理,利於程序項目的擴展。所以在現在的面向對象編程領域中,存在著另外的一個方向——面向接口的編程,其實很多Java的技術都是這樣進行實現的,例如JDBC部分。
由於抽象類和接口的功能比較類似,後續將對於抽象類和接口進行一系列的比較,方便項目設計時的取捨。