java程式設計思想-09介面
介面和內部類為我們提供了一種將介面和現實分離的更加結構化的方法。
1、抽象類和抽象方法
下面是抽象方法宣告所採用的語法:
abstract void f();
包含抽象方法的類叫做抽象類。如果一個類包含一個或多個抽象方法,該類必須被限定為抽象的。(否則,編譯器便會報錯。) 如果一個抽象類不完整,那麼當我們試圖產生該類的物件時,由於為抽象類建立物件是不安全的,所以我們會從編譯器那裡得到一條出錯資訊。這樣,編譯器會確保抽象類的純粹性,我們不必擔心會誤用它。
如果從一個抽象類繼承,並想建立該新類的物件。那麼就必須為基類中的所有抽象方法提供方法定義。如果不這樣做,那麼匯出類便也是抽象類,且編譯器將會強制我們用abstract關鍵字來限定這個類。
建立抽象類和抽象方法非常有用,因為它們可以使類的抽象性明確起來,並告訴使用者和編譯器打算怎樣來使用它們。抽象類還是很有用的重構工具,因為它們使得我們可以很容易地將公共方法沿著繼承層級結構向上移動。
2、介面
interface關鍵字使抽象的概念更向前邁進了一步。abstract關鍵字允許人們在類中建立一個或多個沒有任何定義的方法—提供了介面部分,但是沒有提供任何相應的具體實現。這些實現是由此類的繼承者建立的。interface這個關鍵字產生一個完全抽象的類,它根本就沒有提供任何具體實現。
可以選擇在介面中顯式地將方法宣告為public的,但即使不這麼做, 它們也是public的。因此,當要實現一個介面時,在介面中被定義的方法必須被定義為是public的。否則,它們將只能得到預設的包訪問許可權,這樣在方法被繼承的過程中,其可訪問許可權就被降低了,這是java編譯器所不允許的。
在介面中的每一個方法確實都是一個宣告,這是編譯器所允許的在介面中唯一存在的事物。
3、完全解耦
只要一個方法操作的是類而非介面。那麼你就只能使用這個類及其子類。如果你想要將這個方法應用於不在此繼承結構中的某個類,那麼就不行了。介面可以在很大程度上放寬這種限制。因此,它可以使得我們編寫複用性更好的程式碼。
策略設計模式:建立一個能夠根據所傳遞的引數物件的不同而具有不同行為的方法。這類方法包含所要執行的演算法中固定不變的部分。而“策略”包含變化的部分。策略就是傳遞進去的引數物件,它包含要執行的程式碼。
class Processor{
public String name(){
return getClass().getSimpleName();
}
Object process(Object input){ return input;}
}
class Upcase extends Processor{
String process(Object input){ return ((String)input).toUpperCase();}
}
class Downcase extends Processor{
String process(Object input){ return ((String)input).toLowerCase();}
}
public class Apply{
public static void process(Processor p,Object s){
System.out.print(“Using Processor”+p.name());
System.out.print(p.process(s));
}
String s = "Abcd";
public static void main(String[] args){
process(new Upcase(),s);
process(new Downcase(),s)
}
}
/Output:
Using Processor Upcase
ABCD
Using Processor DownCase
abcd
介面卡設計模式:介面卡中的程式碼將接受你所擁有的介面,併產生你所需要的介面。
class FilterAdapter impletemts Processor{
Filter filter;
public FilterAdapter(Filter filter){
this.filter=filter;
}
}
在這種使用介面卡的方式中,FilterAdapter的構造器接受你所有擁有的介面Filter,然後生成你所需要的Processor介面的物件。
4、Java中的多重繼承
就是實現多個介面。這也是使用介面的核心原因,為了能夠向上轉型為多個基型別(以及由此帶來的靈活性)。然後,使用介面的第二個原因卻是與使用抽象基類相同:防止客戶端程式設計師建立該類的物件,並確保這僅僅是建立一個介面。但這就帶來一個問題,我們應該使用介面還是抽象類?如果要建立不帶任何方法和成員變數的基類,那麼就應該選擇介面而不是抽象類。
interface CanFight{
void fight();
}
interface CanSwim{
void swim();
}
class ActionCharacter{
public void fight();
}
class Hero extends ActionCharacter implements CanFight,CanSwim{
public void swim(){}
}
public class Adventure{
public static void t(CanFight x) { x.fight(); }
public static void u(CanSwim x) { x.swim(); }
public static void w(ActionCharacter x) { x.fight(); }
public static void main(String[] args){
Hero h = new Hero();
t(h);
u(h);
w(h);
}
}
5、通過繼承來擴充套件介面
通過繼承,可以很容易地在介面中新增新的方法宣告,還可以通過繼承在新介面中組合數個介面。
組合介面時的名字衝突:可以過載方法,覆寫方法寫個@Override註解。儘量還是避免不同的介面中使用相同的方法名造成程式碼可讀性的混亂。
6、適配介面
介面最吸引人的原因之一就是允許同一個介面具有多個不同的具體實現。在簡單的情況中,它的體現形式通常是接受一個介面型別的方法,而該介面的實現和向該方法傳遞的物件則取決於方法的使用者。主要就是宣告:“你可以用任何你想要的物件來呼叫我的方法,只要你的物件遵循我的介面”。
7、介面中的域
放入介面中的任何域都自動是static和final的。既然域是static的,它們就可以在類第一次被載入時初始化,這發生在任何域首次被訪問時。當然,這些域不是介面的一部分,它們的值被儲存在該介面的靜態儲存區域內。
8、巢狀介面
介面可以巢狀在類或其他介面中。
9、介面與工廠
工廠方法設計模式非常好用,複用程式碼很方便,與直接呼叫構造器不同,我們在工廠物件上呼叫的是建立方法。該工廠物件將生成介面的某個實現的物件。