接口的定義和類的定義很相似,可以分為接口聲明和接口體積,和類不同的是,使用關鍵字interface來聲明自己是一個接口。
格式如下;
interface 接口的名字
這里需要注意的是:
1、如果一個非抽象類實現了某個接口,那么這個類必須重寫這個接口中的所有方法。
2、如果一個類聲明實現一個接口,但是沒有重寫接口中的從所有方法,那么這個類必須是抽象類,也就是說抽象類既可以重寫接口中的方法,也可以直接擁有接口中的方法。
3、程序可以用接口名訪問接口中的常量,但是如果一個類實現了接口,那么該類可以直接在類體中使用該接口的常量。
4、在我們定義接口的時候,如果關鍵字interface 前面加一個public關鍵字,就成這樣的接口是一個public接口,public接口可以被任何一個類實現。如果一個接口不加public修飾。就稱作是友好接口,友好接口可以被 與該接口在同一個包中的類實現。
5、如果父類實現了某個接口,那么子類自然也就實現了該接口,子類不必再顯式地使用關鍵字implement聲明實現這個接口。
6、接口也可以被繼承,即可以通過關鍵字extends聲明一個接口是另外一個接口的子接口。由於接口中的方法和常量都是public的,子接口將繼承父接口中的全部方法和常量。
舉個例子吧:
在這個例子中China類和Japan類分別繼承computable接口。
下面是具體的源代碼:
China類
1 package Example14; 2 3 import Example5.ComputerAver; 4 5 public class China exends Computable { 6 int number; 7 public int f(int x) { 8 //public關鍵字別漏了 9 int sum = 0; 10 for(int i=1; i<= x;i++){ 11 sum+=i; 12 } 13 return sum; 14 } 15 //重寫方法f 16 }
Japan類
1 package Example14; 2 3 public class Japan extends Computable { 4 int number; 5 @Override 6 public int f(int x) { 7 return MAX + x; 8 //直接調用接口中的常量 9 } 10 11 }
computable接口
1 package Example14; 2 3 public interface Computable { 4 int MAX = 46; 5 public abstract int f(int x); 6 }
主函數:
1 package Example14; 2 3 public class Demo { 4 5 public static void main(String[] args) { 6 China zhang; 7 Japan henlu; 8 zhang = new China(); 9 henlu = new Japan(); 10 zhang.number = 32 + Computable.MAX; 11 henlu.number = 14 + Computable.MAX; 12 System.out.println("zhang的學號" + zhang.number + " zhang求和結果" + zhang.f(100)); 13 System.out.println("henlu的學號" + henlu.number + " henlu求和結果" + henlu.f(100)); 14 } 15 16 }
運行結果:
zhang的學號78 zhang求和結果5050
henlu的學號60 henlu求和結果146
例子2:
動機類MotorVehicles :
1 package Example15; 2 3 interface MoneyFare { 4 void charge(); 5 }
空調接口ControlTemperature:
1 package Example15; 2 3 interface ControlTemperature { 4 void controlAirTemperature(); 5 }
Bus類繼承了動機類並且實現了收費接口
1 package Example15; 2 //bus實現MoneyFare 3 //一個接口 4 5 public class Bus extends MotorVehicles implements MoneyFare{ 6 7 void brake(){ 8 System.out.println("公共汽車使用轂式剎車"); 9 }//重寫 10 11 public void charge() { 12 System.out.println("公共汽車:一元/張,不計算公里數"); 13 } 14 15 16 }
Taxi類繼承了動機類並且實現了空調和收費接口
1 package Example15; 2 3 public class Taxi extends MotorVehicles implements MoneyFare ,ControlTemperature { 4 5 6 public void charge() { 7 System.out.println("出租車:2元/公里,起價3公里"); 8 } 9 10 11 void brake() { 12 System.out.println("出租車使用盤式剎車技術:"); 13 } 14 15 16 public void controlAirTemperature() { 17 System.out.println("出租車安裝了Hair空調"); 18 } 19 20 }
Cinrma 實現了空調和收費接口
1 package Example15; 2 3 public class Cinrma implements MoneyFare, ControlTemperature { 4 5 @Override 6 public void controlAirTemperature() { 7 System.out.println("電影院安裝了中央空調"); 8 } 9 10 @Override 11 public void charge() { 12 System.out.println("電影院:門票,10/張"); 13 } 14 15 }
主函數調用
1 package Example15; 2 3 public class Demo { 4 5 public static void main(String[] args) { 6 Bus bus = new Bus(); 7 Taxi taxi = new Taxi(); 8 Cinrma cinrma = new Cinrma(); 9 bus.brake(); 10 bus.charge(); 11 taxi.charge(); 12 taxi.brake(); 13 taxi.controlAirTemperature(); 14 cinrma.charge(); 15 cinrma.controlAirTemperature(); 16 } 17 18 }
調試結果:
公共汽車使用轂式剎車 公共汽車:一元/張,不計算公里數 出租車:2元/公里,起價3公里 出租車使用盤式剎車技術: 出租車安裝了Hair空調 電影院:門票,10/張 電影院安裝了中央空調
關於接口回調
和類一樣,接口也是Java中一種重要的數據類型,用接口聲明的變量稱作接口變量。
接口屬於引用型變量,接口變量中可以存放實現該接口類的實例應引用,即存放對象的引用。
“接口回調”這個詞是借用了C語言中的指針回調的術語,表示一個變量的地址在某一個時刻放在一個指針變量中,那么指針變量就可以間接操作該變量中存放的數據。
在Java語言中,接口回調是指:可以把實現某一接口的類創建的對象的引用賦值給該接口聲明的接口變量,那么該接口變量就可以調用被類實現的接口方法。事實上,當接口變量調用被類實現的接口方法時,就是通知相應的對象調用這個方法。
舉個例子:假設Com是一個接口,ImpleCom類是實現Com接口的類
Com com; ImpleCom impleCom; com = impleCom;// 這樣是合法的。將impleCom 的對象的引用賦值給com接口。
類似上轉型對象調用子類重寫的方法
下面我們舉個例子:
ShowMessage 接口:
package Example16; public interface ShowMessage { void 顯示商標(String s); }
PC類實現了ShowMessage接口
package Example16; public class PC implements ShowMessage { public void 顯示商標(String s) { System.out.println(s); } }
TV類實現了ShowMessage 接口:
package Example16; public class TV implements ShowMessage { public void 顯示商標(String s) { System.out.println(s); } }
主函數:
package Example16; public class Demo { public static void main(String[] args) { ShowMessage message; message = new TV(); message.顯示商標("長虹牌電視機"); message = new PC(); message.顯示商標("華碩A550jk4200"); } }
調試結果
長虹牌電視機 華碩A550jk4200
關於接口和多態:
接口產生的多態就是指不同的類在實現同一個接口時可能具有不同的實現方法,那么接口變量在回調接口方法是就可能具有多種形態。
下面我們舉個例子:
接口ComputerAverage :
package Example17; interface ComputerAverage { public double average(double a,double b); }
類A實現接口ComputerAverage
package Example17; public class A implements ComputerAverage { public double average(double a, double b) { double aver = 0; aver = (a+b)/2; return aver; } }
類B實現接口ComputerAverage
package Example17; public class B implements ComputerAverage { public double average(double a, double b) { double aver = 0; aver = Math.sqrt(a*b); return aver; } }
主函數調用:
package Example17; public class Demo { public static void main(String[] args) { ComputerAverage average; double a = 11.45,b = 45.45; average = new A(); double result = average.average(a, b); System.out.println(a + "和" + b + "的算術平均值:" + result ); average = new B(); result = average.average(a, b); System.out.println(a + "和" + b + "的幾何平均值:" + result ); } }
調試結果:
11.45和45.45的算術平均值:28.450000000000003 11.45和45.45的幾個平均值:22.81233219116362
在這個例子中類A和類B都實現了ComputerAverage接口,但是實現的方式不同。
關於接口參數:
如果一個方法參數的類型是接口類型,我們就可以將任何實現該接口的類的實例的引用傳遞給接口參數,那么接口參數就可以回調類實現的接口方法,下面舉個例子:
基本接口SpeakHello.java
package Example18; interface SpeakHello { void speakHello(); }
Chinese類實現接口:
package Example18; public class Chinese implements SpeakHello { public void speakHello() { System.out.println("中國人習慣問候語:你好!吃飯了嗎?"); } }
English類實現接口
package Example18; public class English implements SpeakHello { public void speakHello() { System.out.println("英國人習慣性用語:你好,天氣不錯!"); } }
KindHello類使用接口類型參數,實現接口回調
package Example18; public class KindHello { public void lookHello(SpeakHello hello) { //接口類型參數,接口回調 hello.speakHello(); } }
主調用函數:
1 package Example18; 2 3 public class Demo { 4 5 public static void main(String[] args) { 6 KindHello kindHello = new KindHello(); 7 kindHello.lookHello(new Chinese()); 8 kindHello.lookHello(new English()); 9 } 10 11 }
調試結果:
1 中國人習慣問候語:你好!吃飯了嗎? 2 英國人習慣性用語:你好,天氣不錯!
abstract類與接口的比較:
1、abstract類和接口都可以有abstract方法。
2、接口中只可以有常量,不能有變量;而abstract類中既可以有常量也可以有變量。
3、abstract類中也可以有非abstract方法,而接口必須是抽象方法。
需要注意的是:
在設計程序時應當根據具體的方法來確定是使用抽象類還是接口。abstract類除了提供重要的需要子類重寫的abstract方法之外,也提供了子類可以繼承的變量和非abstract方法。如果某個問題需要使用繼承才能更好地解決,比如:子類除了需要重寫父類的abstract方法,還需要從父類繼承一些變量或者繼承一些重要的非abstract方法,就可以考慮使用abstract類。如果某個問題不需要繼承,只是需要若干個子類給出某些重要的abstract方法的實現細節,就可以考慮使用接口。
一個面向接口編程的應用舉例:
問題的提出:
設計一個廣告牌,希望所設計的廣告牌可以展示許多公司的廣告詞。
1、問題的分析:
如果我們設計的創建廣告牌的類中是某個具體公司類。(例如聯想公司類),聲明了對象。那么我們的廣告牌就缺少彈性,因為用戶一旦需要廣告牌展示其他公司的廣告詞,就需要修改廣告牌類的代碼,比如用長虹公司聲明成員變量。
如果沒當用戶有了新的需求,就會導致修改類的某部分代碼,那么就應當將這部分代碼從該類重分割出去,使它和其他穩定的代碼之間是松耦合的關系(否則系統缺乏彈性,難以維護),即將每種可能的變化對應地交給實現接口的類(抽象類的子類)去負責完成。
2、設計接口。
根據以上的對問題的分析,首先設計一個接口Advertisement,改接口有2個方法show-Advertisement()和getCorpName();那么實現Advertisement接口的類必須重寫,show-Advertisement()和getCropName()方法,及要求各個公司給出具體的廣告詞和公司的名稱。
3、設計廣告牌類
然后我們設計AdvertisementBoard類(廣告牌),該類有一個show(Advertisement adver)方法,該方法的參數adver是Advertisement接口類型(就像人們常說的,廣告牌對外留有接口)。顯然,該及參數adver可以存放任何實現Advertisement接口的類的對象的引用,並且回調重寫的接口方法ShowAdvertisement()來顯示公司的廣告詞,回調類重寫的接口方法getCropName()來顯示公司的名稱。
下面是具體實現的代碼:
廣告Advertisement接口:
1 package Example19; 2 /** 3 * 接口 4 * @author 10497 5 * 6 */ 7 public interface Advertisement { 8 public void ShowAdvertisement(); 9 public String getCropName(); 10 }
廣告牌類,完成接口回調:
1 package Example19; 2 /** 3 * 廣告牌類 4 * @author 10497 5 * 6 */ 7 8 public class AdvertisementBoard { 9 public void Show(Advertisement adver){//使用接口參數 10 System.out.println(adver.getCropName() + "的廣告詞如下:"); 11 adver.ShowAdvertisement(); 12 //接口回調 13 } 14 }
安踏公司實現接口:
1 package Example19; 2 3 public class AnTaCrop implements Advertisement { 4 5 public void ShowAdvertisement() { 6 System.out.println("@@@@@@@@@@@@@@@@@@@"); 7 System.out.println("安踏,運動永不止步~~"); 8 System.out.println("@@@@@@@@@@@@@@@@@@@"); 9 } 10 11 public String getCropName() { 12 return "安踏有限公司"; 13 } 14 15 }
特步公司實現接口
package Example19; public class TeBuCorp implements Advertisement { public void ShowAdvertisement() { System.out.println("**********************"); System.out.println("特步,非一般的感覺~~~~~"); System.out.println("**********************"); } public String getCropName() { return "特步有限公司"; } }
主調用函數:
1 package Example19; 2 3 public class Application { 4 public static void main(String args[]){ 5 AdvertisementBoard board = new AdvertisementBoard(); 6 board.Show(new AnTaCrop()); 7 board.Show(new TeBuCorp()); 8 } 9 }
調試結果:
1 安踏有限公司的廣告詞如下: 2 @@@@@@@@@@@@@@@@@@@ 3 安踏,運動永不止步~~ 4 @@@@@@@@@@@@@@@@@@@ 5 特步有限公司的廣告詞如下: 6 ********************** 7 特步,非一般的感覺~~~~~ 8 **********************