JAVA中的“抽象接口”


       在程序設計過程中,讀者很可能遇到這樣一種困境:設計了一個接口,但實現這個接口的子類並不需要實現接口中的全部方法,也就是說,接口中的方法過多,對於某些子類是多余的,我們不得不浪費的寫上一個空的實現。

       今天小菜提到的“抽象接口”,就是用來解決這個問題的。

       為了不誤導讀者,先說明一下,什么是“抽象接口”。

       所謂“抽象接口”,即在提供接口的同時,提供一個抽象類,用抽象類實現該接口(實際上這是缺省適配模式)。

       下面小菜舉個例子,讓讀者體會這樣做的好處。

       代碼寫的不咋地,為了防止讀者看不懂,先上一張類圖:

具體代碼:

  ITestInterface.java

1 /*
2     假設有一個頂層接口
3 */
4 public interface ITestInterface{
5     void method1();
6     int method2();
7     boolean method3();
8 }

 

 

  TestAbstract.java

 1 /*
 2     抽象類abstract實現了ITestInterface頂層接口
 3 */
 4 
 5 public abstract class TestAbstract implements ITestInterface{
 6     //找出接口中必要的方法,也就是子類必須實現的方法,定義成抽象方法,交由子類實現
 7     public abstract void method1();
 8     public abstract int method2();
 9     
10     //一些獨特的方法可以在抽象類中默認實現
11     public boolean method3(){
12         return true;
13     }
14 }

 

  

  TestClass1.java

 1 /*
 2     普通類TestClass1繼承了TestAbstract抽象類
 3 */
 4 
 5 public class TestClass1 extends TestAbstract{
 6     
 7     //TestClass1必須實現抽象的method1方法,該方法最早是接口中定義的
 8     public void method1(){
 9         
10     }
11     //TestClass1必須實現抽象的method2方法,該方法最早是接口中定義的
12     public int method2(){
13         return 1;
14     }
15     
16     //接口中的method3方法對於TestClass1無關緊要,因此不做重寫。
17 }

 

 

  TestClass2.java

 1 /*
 2     普通類TestClass2繼承了TestAbstract抽象類
 3 */
 4 
 5 public class TestClass2 extends TestAbstract{
 6     
 7     //TestClass2必須實現抽象的method1方法,該方法最早是接口中定義的
 8     public void method1(){
 9     
10     }
11     //TestClass2必須實現抽象的method2方法,該方法最早是接口中定義的
12     public int method2(){
13         return 2;
14     }
15     
16     //method3方法對於TestClass2來說至關重要,因此必須重寫。
17     public boolean method3(){
18         return false;
19     }
20     
21 }

 

 

代碼精講:

    從以上例子可以看出,最高層的接口被一個抽象類實現,在抽象類中,我們把關鍵的method1、method2方法定義成抽象方法,強制子類去實現,而“獨特”的method3方法在抽象類中做一個默認實現。

    等到TestClass1、TestClass2繼承TestAbstract抽象類時,優勢就體現出來了,TestClass1、TestClass2必須實現method1、method2,但如果用不到method3,可以直接無視。

    通過接口和抽象類的結合,避免了在實現接口的子類中出現大量的“無意義”實現,這個“無意義”實現,被緩沖到了抽象類中,完美展現了代碼復用(可以把抽象類理解成接口和實現類之間的緩沖)。

    需要指出的是,我們既可以選擇繼承抽象類,也可以選擇實現接口,並不是說一定要繼承抽象類,看情況而定,這里是兩種選擇,兩個機會。

      

              寫到這,或許讀者覺得文章已經結束了,其實沒有。。。

              這樣做的好處不僅僅是這一點,細細品味,假如我們向接口中增加了一個方法。。。

 

具體代碼:

  溫馨提示:不要被代碼嚇到,其實這些代碼和上邊的差不多,只不過加了個方法而已。

 

  ITestInterface.java

 1 /*
 2     假設有一個頂層接口
 3 */
 4 public interface ITestInterface{
 5     void method1();
 6     int method2();
 7     boolean method3();
 8     //接口中新增加了方法
 9     String method4();
10 }

 

 

  TestAbstract.java

 1 /*
 2     抽象類abstract實現了ITestInterface頂層接口
 3 */
 4 
 5 public abstract class TestAbstract implements ITestInterface{
 6     //找出接口中必要的方法,也就是子類必須實現的方法,定義成抽象方法,交由子類實現
 7     public abstract void method1();
 8     public abstract int method2();
 9     
10     //一些獨特的方法可以在抽象類中默認實現
11     public boolean method3(){
12         return true;
13     }
14     
15     //抽象類中提供一個默認實現,這樣就可以避免"驚動"所有子類
16     public String method4(){
17         return "";
18     }
19 }

 

 

  TestClass1.java

 1 /*
 2     普通類TestClass1繼承了TestAbstract抽象類
 3 */
 4 
 5 public class TestClass1 extends TestAbstract{
 6     
 7     //TestClass1必須實現抽象的method1方法,該方法最早是接口中定義的
 8     public void method1(){
 9         
10     }
11     //TestClass1必須實現抽象的method2方法,該方法最早是接口中定義的
12     public int method2(){
13         return 1;
14     }
15     
16     //接口中的method3方法對於TestClass1無關緊要,因此不做重寫。
17     
18     //新增的方法對於TestClass1來說至關重要,因此必須重寫
19     public String method4(){
20         return "Class1";
21     }
22 
23 }

 

 

  TestClass2.java

 1 /*
 2     普通類TestClass2繼承了TestAbstract抽象類
 3 */
 4 
 5 public class TestClass2 extends TestAbstract{
 6     
 7     //TestClass2必須實現抽象的method1方法,該方法最早是接口中定義的
 8     public void method1(){
 9     
10     }
11     //TestClass2必須實現抽象的method2方法,該方法最早是接口中定義的
12     public int method2(){
13         return 2;
14     }
15     
16     //method3方法對於TestClass2來說至關重要,因此必須重寫。
17     public boolean method3(){
18         return false;
19     }
20     
21     //新增的方法對於TestClass2來說無關緊要,無需知道新增method4的存在
22 }

 

 

代碼精講:

    這段代碼演示了假如項目已經成型,但是需求有變,我們不得不向接口中增加一個新的方法,假如子類直接實現了接口,那么這些子類都要修改,來實現接口新增的方法。

    但本例中的TestClass1、TestClass2子類沒有直接實現接口,而是通過繼承抽象類間接實現接口,這樣好處一下就體現出來了!

    向接口中新增的方法,可以在實現接口的抽象類中緩沖一下,提供一個默認的實現,這樣一來,就不必強制所有的子類(通過繼承抽象類間接實現接口的類)都進行修改,可以形象的理解為“沒有驚動子類”。而需要使用這個方法的子類,直接重寫即可。

 

小菜感慨:

 

    人類的智慧真偉大!數組和鏈表結合,產生了高效的哈希表;接口和抽象類結合,產生了優雅的缺省適配模式。大家努力吧!!!

 

寫在后面的話:

    世間沒有完美的事物,設計模式也是如此,過多的討論優缺點沒有意義,合適的就是最好的,什么是合適的呢?這才是體現智慧的地方。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM