qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Java在線教程——接口篇

            Interfaces 接口

            在軟件工程中,由一份“契約”規定來自不同的開發小組的軟件之間如何相互作用是非常常見的。每個小組都可以在不知道別的組的代碼的前提下獨立開發自己的代碼。Java中的interface就是這樣的一份“契約”。

            舉個例子,假設在未來社會有一種智能汽車,它可以在自動運載旅客而不需要人工操作。汽車生產商開發了軟件(當然是用Java)來控制這種汽車停止,發動,加速,左轉等等。電子導航儀器生產商負責開發接受GPS位置數據和交通狀況無線傳輸的電腦系統,并且應用這些信息來駕駛汽車。

            汽車生產商必須公布工業標準interface,該interface需詳細解釋哪些methods可以用于控制汽車運動(該標準適用于任何汽車,任何生產商)。導航系統生產商就可以應用這個interface所介紹的各種methods來控制汽車。任何一個工業廠商都不需了解其他廠商是如何實現他們的軟件的。事實上,只要大家都嚴格遵守所公布的interface,每個廠商對其自己的軟件都有高度所有權,并且保有隨時修改的權利。

            在java中的interface

            在java編程語言里,一個interface是引用類型(reference),它與class相似,因此只能包含常量(constants),方法簽名(method signatures)和嵌套類型(nested types)。Interface不得含有方法的具體代碼(method body)。 Interface 不可被實例化(instantiated),只能被其它class實現(implemented)或者被其它interface繼承。

            定義一個interface與創建一個新類類似:

          1. public interface OperateCar {  
          2. // constant declarations, if any 
          3. // method signatures 
          4. // An enum with values RIGHT, LEFT 
          5.    int turn(Direction direction,  
          6.             double radius,  
          7.             double startSpeed,  
          8.             double endSpeed);  
          9.    int changeLanes(Direction direction,  
          10.                    double startSpeed,  
          11.                    double endSpeed);  
          12.    int signalTurn(Direction direction,  
          13.                   boolean signalOn);  
          14.    int getRadarFront(double distanceToCar,  
          15.                      double speedOfCar);  
          16.    int getRadarRear(double distanceToCar,  
          17.                     double speedOfCar);  
          18.          ……  
          19.    // more method signatures 
          20. }

            如想使用上面這個interface,你需要寫一個class來實現它。當一個可被實例化的class實現某個接口時,它需要提供所有該interface所聲明的所有方法(methods)的具體代碼。

            在上面的自動化汽車的例子中,汽車生產商即是接口實現者。由雪佛蘭公司的實現方法當然不同于本田公司的方法,但是它們都遵循同一個接口。 導航系統生產商是這個接口的使用者,他們的系統將根據汽車方位的GPS數據,數字化地圖和交通情況來駕駛汽車。因此,這個導航系統將會涉及以下的方法(methods): 轉彎,切道,剎車,加速等等。

            API 接口

            自動化汽車的例子展示了interface在工業標準應用程序接口(API, Application Programming Interface)中的應用. 在商業軟件中,API也很常見。 通常來說,一個公司發售的軟件包中會含有其他公司希望應用在自己的產品中的復雜方法(methods)。比如一個包含了數字圖形處理方法的軟件包就可以出售給開發終端客戶圖像軟件的公司。購買后,該公司就可以應用interface所定義的方法。當圖像處理公司向所有客戶公開它的API的同時,這些API的實現方法是高度保密的。事實上,只要保留住原始的interface不被改變,這些API的實現方法很可能在將來被重寫。

            Interfaces 和多重繼承

            在java編程語言里,interface還有另外一個重要作用。 盡管Interface是與類一起使用的,但它并不是類的層次結構的一部分。java編程語言不支持多重繼承,但是interface提供了替代方案。

            在java中,一個類只能繼承于單一的類,但是它可以實現多個接口。因此,對象可以有多重類型:屬于它自身類的類型,和屬于它所繼承的所有接口的類型。這意味著,如果聲明一個變量是某個接口類型,這個變量可以指代任何實現該接口的類的實例。這部分會在“使用接口類型”中詳細討論。

           定義一個interface

            一個接口的定義是由 修飾詞(modifiers),關鍵詞 interface, 接口名稱,由逗號分隔開的父接口(parent interfaces),和接口實體(interface body)。

            例子如下:

          1. public interface GroupedInterface extends Interface1, Interface2, Interface3 {  
          2. // constant declarations  
          3. // base of natural logarithms  
          4.     double E = 2.718282;  
          5. // method signatures   
          6.     void doSomething (int i, double x);  
          7.     int doSomethingElse(String s);  
          8. }

            Public規定了這個接口可以被任何包中的任何類所使用。如果你聲明這個接口是public的,它只能被同一個包里的類所使用。

            一個接口可以繼承其它接口,就像一個類能后繼承其它類一樣。但是類只能繼承一個父類,而接口卻可以繼承任何數目的接口。

            接口實體(interface body)

            接口實體中含有它所包含的所有方法的聲明。每個聲明都以引號為結束,因為接口不用實現它所聲明的方法。接口中所有的方法都默認是public的,因此修飾詞public可以被省略。

            接口還可以聲明常量。同樣的,常量的修飾詞public, static和final可以被省略。

            接口的實現

            為了聲明某個類實現了某個接口,你需要在類的聲明中使用implements。你的類可以實現多個接口,所以implements關鍵詞后面可以跟隨多個由逗號分隔的接口名稱。為了方便,implements關鍵詞多跟在extends關鍵詞的后面。

            一個接口實例—Relatable

            Relatable是一個用來比較兩個對象大小的接口。

          1. public interface Relatable {  
          2.     // this (object calling isLargerThan)  
          3.     // and other must be instances of   
          4.     // the same class returns 1, 0, -1   
          5.     // if this is greater // than, equal   
          6.     // to, or less than other  
          7.     public int isLargerThan(Relatable other);  
          8. }

            如果你想比較兩個相似的對象的大小,不管該對象屬于什么類,這個類需要實現Relatable接口。

            只要有辦法可以比較對象的相對大小,任何類都可以實現Relatable接口。對字符串來說,可以比較字符數;對書來說,可以比較頁數;對學生來說,可以比較體重。對平面幾何對象來說,比較面積是很好的選擇;對三維對象來說,就需要比較體積了。所有以上的類都能實現int isLargerThan()方法。

            如果你知道某個類實現了Relatable接口,你可以比較從這個類實例化的對象了。

            Relatable接口的實現

            下面是一個三角形類,它實現了Relatable接口。

          1. public class RectanglePlus  
          2.     implements Relatable {  
          3.     public int width = 0;  
          4.     public int height = 0;  
          5.     public Point origin;  
          6.     // four constructors  
          7.     public RectanglePlus() {  
          8.         origin = new Point(00);  
          9.     }  
          10.     public RectanglePlus(Point p) {  
          11.         origin = p;  
          12.     }  
          13.     public RectanglePlus(int w, int h) {  
          14.         origin = new Point(00);  
          15.         width = w;  
          16.         height = h;  
          17.     }  
          18.     public RectanglePlus(Point p, int w, int h) {  
          19.         origin = p;  
          20.         width = w;  
          21.         height = h;  
          22.     }  
          23.     // a method for moving the rectangle  
          24.     public void move(int x, int y) {  
          25.         origin.x = x;  
          26.         origin.y = y;  
          27.     }  
          28.     // a method for computing  
          29.     // the area of the rectangle  
          30.     public int getArea() {  
          31.         return width * height;  
          32.     }  
          33.     // a method required to implement  
          34.     // the Relatable interface  
          35.     public int isLargerThan(Relatable other) {  
          36.         RectanglePlus otherRect   
          37.             = (RectanglePlus)other;  
          38.         if (this.getArea() < otherRect.getArea())  
          39.             return -1;  
          40.         else if (this.getArea() > otherRect.getArea())  
          41.             return 1;  
          42.         else 
          43.             return 0;  
          44.     }  
          45. }




          使用接口類型

            在你定義一個新的接口時,你其實在定義一個新的引用類型。在你能使用數據類型名稱的地方,都可以使用接口名稱。如果你定義了一個類型為接口的引用變量,該變量能指向的對象所在的類必須實現了該接口。

            下例是一個在一對對象中返回較大對象的方法:

          1. public Object findLargest(Object object1, Object object2) {  
          2.    Relatable obj1 = (Relatable)object1;  
          3.    Relatable obj2 = (Relatable)object2;  
          4.    if ((obj1).isLargerThan(obj2) > 0)  
          5.       return object1;  
          6.    else 
          7.       return object2;  
          8. }

            通過把數據類型object1轉換成Relatable,對象obj1可以調用isLargerThan方法。

            同理,只要是實現了Relatable的類,也可以使用下面的方法。

          1. public Object findSmallest(Object object1, Object object2) {  
          2.    Relatable obj1 = (Relatable)object1;  
          3.    Relatable obj2 = (Relatable)object2;  
          4.    if ((obj1).isLargerThan(obj2) < 0)  
          5.       return object1;  
          6.    else 
          7.       return object2;  
          8. }  
          9. public boolean isEqual(Object object1, Object object2) {  
          10.    Relatable obj1 = (Relatable)object1;  
          11.    Relatable obj2 = (Relatable)object2;  
          12.    if ( (obj1).isLargerThan(obj2) == 0)  
          13.       return true;  
          14.    else 
          15.       return false;  
          16. }

            這些方法適用于任何“Relatable”的類,而無關它們的繼承關系。實現了Relatable的類,它們既屬于自身(或者父類)的類型,也屬于Relatable類型。這使得它們具有了多重繼承的優點,因為它們可以同時具備父類和接口的行為。

            重寫接口

            假設你開發了一個接口名為DoIt:

          1. public interface DoIt {  
          2.    void doSomething(int i, double x);  
          3.    int doSomethingElse(String s);  
          4. }

            然后,你想加入一個新的方法在這個接口里,因此代碼變成:

          1. public interface DoIt {  
          2.    void doSomething(int i, double x);  
          3.    int doSomethingElse(String s);  
          4.    boolean didItWork(int i, double x, String s);  
          5. }

            如果你這么修改了,所有實現了舊的DoIt接口的類都會出錯,因為它們不再正確的實現這個接口。所有使用這個接口的程序員會嚴重抗議你的修改。

            你需要預估你的接口用戶的需求,并從開始就完善的設計好這個接口。但是這常常是無法做到的。另一個解決方法就是再寫一個接口。例如,你可以寫一個DoItPlus的接口繼承原有的接口。

          1. public interface DoItPlus extends DoIt {  
          2.    boolean didItWork(int i, double x, String s);  
          3. }

            現在你的用戶可以選擇繼續使用舊接口DoIt,或是升級的新接口DoItPlus。

            總結

            接口就是兩個對象間的溝通協議。

            一個接口的聲明包含一些方法的簽名(signatures),但不需要實現它們;也可能含有一些常量。

            實現某接口的類必須實現該接口所聲明的所有的方法。

            在任何使用類型名稱的地方都可以使用接口的名字。

          posted on 2013-01-25 09:31 順其自然EVO 閱讀(188) 評論(1)  編輯  收藏

          評論

          # re: Java在線教程——接口篇 2013-01-25 13:03 免費網絡記事本

          這篇文章很不錯,寫得也很詳細。對于我們這種新手來說,很有幫助,非常感謝!!  回復  更多評論   


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2013年1月>
          303112345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 寻甸| 宁国市| 芜湖市| 西和县| 友谊县| 普洱| 耒阳市| 滕州市| 伽师县| 海城市| 山东省| 通海县| 剑川县| 嘉峪关市| 手游| 泊头市| 榆社县| 深州市| 疏附县| 射洪县| 栖霞市| 清原| 贵阳市| 集贤县| 乌苏市| 怀集县| 昔阳县| 永寿县| 德惠市| 灵武市| 郎溪县| 兴义市| 丰宁| 九江县| 大姚县| 南郑县| 徐州市| 南康市| 霞浦县| 枣庄市| 福州市|