Java編程思想——細話Java接口

接口爲我們提供了一種將接口與實現分離的更加結構化的方法。在選擇使用接口通常有倆個目的:

  • 一是,爲了可以向上轉型
  • 二是,避免被創建對象(實例),這一點和抽象類是一致的。

任何抽象性都是應真正的需求而產生的,所以在開發中不能一味地使用接口,而要根據設計的需求。

《Java編程思想》給出的建議是:優先選擇類,如果接口的必需性變得非常明確,那麼就進行重構

一、抽象類和抽象方法

抽象類提供一批通用接口,希望可以通過這些接口操縱一系列類

抽象方法——一種不完整的方法,只有聲明而沒有方法體,具體如下

abstract void f();//含有關鍵字abstract

抽象類——即含有一個或多個抽象方法,並用關鍵字abstract修飾的類

//創建抽象類
abstract Animal{ 
   public void eat(String time);//抽象方法
   public void sleep(){
      System.out.print("Sheep!");
   }
}

class Dog extends Animal{
   public void eat(String time){    
     System.out.print("Dog "+time+"eat meat!");
   }
}
class Sheep extends Animal{
   public void eat(String time){
    System.out.print("Sheep "+time+"eat grass");
   }
}
public class Test{
   public void turn(Animal a){
      a.eat("8:00");
      a.sleep();
   }
   public static void main(String[] args){
     Animal[] a={new Dog(),new  Sheep()};
     for(Animal sub:a){
       turn(sub);
     }
    }
}
out:
Dog 8:00 eat meat!
Sleep!
Sheep 8:00 eat grass!
Sleep!

需要注意一點的是,抽象類是不能進行實例化的,所以Java爲了讓用戶可以很清晰的清楚這一點採用了”抽象方法的機制“,利用其不完整性和關鍵字abstract的使用來告知編譯器自身的特殊性,防止誤導使用者。

二、接口

       interface是一個極度抽象的類,接口裏面的方法同樣沒有方法體,它的存在就是爲了保持一部分其他類的一致性。創建一個接口需要用關鍵字interface代替class,關鍵字前可以添加限定修飾符,但是如同類一樣,一個接口文件中只能有一個public修飾的接口,且接口名必須與文件名一致。接口同樣可以包含域,但是這些域隱式的是static和final

接口的使用形式很像繼承,但是與繼承又有很大區別,繼承要求每一子類只能繼承一個父類,但是接口則可以通過implements關鍵字進行多個接口的實現(相當於創建了一個可以向上轉型爲多種基類的類型,很像多重繼承),

需要注意的是在接口中所有的方法都應該被聲明爲public,因爲Java編譯器是不允許接口的訪問權限被降低的。

接口的具體實例如下:

package com.interface;
//創建接口
public interface Animal{ 
   String time="8:00";//static&final
   public void eat(String time);
   public void sleep();
}
package com.animalclass;
import com.interface.Animal;//導入接口

class Dog implements Animal{
   public void eat(String time){    
     System.out.print("Dog "+time+"eat 
 meat!");
   }
   public void sleep(){
     System.out.print("Dog sleep!");
   }
}
class Sheep implements Animal{
   public void eat(String time){
    System.out.print("Sheep "+time+"eat 
 grass");
   }
   public void sleep(){
     System.out.print("Sheep sleep");
   }
}
public class Test{
   public void turn(Animal a){
      a.eat(Animal.time);//time默認爲static,所以可以通過接口名直接調用
      a.sleep();
   }
 public static void main(String[] args){
     Animal[] a={new Dog(),new  Sheep()};
     for(Animal sub:a){
       turn(sub);
     }
    }
}
out:
Dog 8:00 eat meat!
Dog sleep!
Sheep 8:00 eat grass!
Sheep sleep!

三、接口中的域

  • 默認都是static和final類型的,且自動是public的;
  • 不能是變量,不能是“空final”,但可以是非常量表達式;
Random RAND=new Random(20);
int ONE=RAND.nextInt(10);
double TWO=RAND.nextDouble()*10;
//注:這些域並不屬於這個接口的一部分,它們被存儲在該接口的靜態存儲區域內,可通過接口名直接調用

  • 接口域在Java沒有枚舉enum時起到了補充的作用,但是現在很少在接口中創建域。

四、嵌套接口

即接口之間可以進行互相嵌套,這種嵌套主要分爲倆種:

  • 類中嵌套接口
class A{
   public interface B{void show();}
   public interface C{void show();}
   public interface D{void show();}
   //嵌套的也可以是私有接口,但是此時的接口不能被外部類或者接口進行訪問,只能是通過方法(類似於訪問類中的私有成員變量需要get方法)
   private interface E{void show();}
}

  • 接口中嵌套接口
interface A{
   public interface B{void show();}
   public interface C{void show();}
   public interface D{void show();}
}

除了上述內容,書中還介紹了關於接口的完全解耦的問題和接口在設計模式中的應用(策略設計模式、工廠設計模式),關於這倆點感覺很抽象,所以會在後邊重點學習和記錄。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章