【Java編程思想】9.接口
接口和內部類為我們提供了一種將接口與實現分離的更加結構化的方法。
9.1 抽象類和抽象方法
Java 提供抽象方法機制,這種方法時不完整的,僅有聲明,沒有方法體。
包含抽象方法的類叫做抽象類。如果一個類包含一個或多個抽象方法,那麽該類必須被限定為是抽象的(否則編譯器報錯)。
一個抽象類不完整的時候,試圖創建對象時,編譯器會出錯(為抽象類創建對象是不安全的),編譯器會保證抽象類的純粹性。
從一個抽象類繼承後,如果想創建該導出類的對象,那麽必須為基類中所有抽象方法提供方法實現。不這麽做,導出類便也是抽象類,編譯器會強制使用 abstract
關鍵字限定導出類。
抽象類和抽象方法不僅讓類的抽象性明確起來,而且抽象類在重構的時候,可以方便的將公共方法沿著繼承層級結構向上移動。
9.2 接口
abstract
關鍵字允許在類中創建一個或多個沒有任何定義的方法-->提供了接口部分,但是沒有提供任何相應的具體實現(其實抽象類中也可以選擇實現個別方法)。interface
關鍵字比抽象類跟進了一步,其會產生一個完全抽象的類,沒有提供任何實現,只允許定義方法名、參數列表和返回類型,沒有任何方法體。
一個接口代表著“所有實現了該特定接口的類看起來都這個樣”。所以接口被用來建立類與類之間的協議。
接口中的方法隱式的被視為 public 的。
接口可包含域,這些域隱式的是 static 和 final 的。
當使用一個類去實現接口時,使用 implements
關鍵字,表示”interface 只是其外貌,現在我要聲明它是如何工作的
9.3 完全解耦
創建一個能夠根據所傳遞的參數對象的不同而具有不同行為的方法,被稱為策略設計模式。這類方法包含所要執行的算法中固定不變的部分,而”策略“包含變化的部分。
此章節還講解了適配器設計模式,關於設計模式可以查看歸檔資料中的 Java 設計模式。
9.4 Java 中的多重繼承
Java 中可以組合多個接口,被稱為多重繼承。
在導出類中,不強制要求必須有偶一個是抽象的或者是“具體的”基類。繼承類只能一次,但是實現接口可以有若幹個。實現的多個接口,都可以向上轉型為每個接口(因為每個接口都是一個獨立類型)。
使用接口的核心原因:
- 能夠向上轉型為多個基類類型(以及由此而帶來的靈活性)。
- 防止客戶端程序員創建該類的對象,並確保這僅僅是建立一個接口
- 創建不帶任何方法定義和成員變量的基類,就應該選擇接口,而不是抽象類。
9.5 通過繼承來拓展接口
一個接口可以繼承其他多個接口。來實現方法的拓展。
一般情況下只可以將 extends 用於單一類的繼承,但是也用多個基類接口。
在不同接口中,最好不要使用相同名稱的方法,會造成可讀性混亂,以及覆蓋、實現和重載混雜在一起的結果。
9.6 適配接口
關於策略設計模式:需要編寫一個執行某些操作的方法,該方法接收一個指定的接口。然後聲明:可以使用任何需要的對象來調用方法,只要這個對象遵循指定的接口。
到這裏說句題外話,雖然內容上接口部分比繼承少了許多,但是接口的思想以及在設計模式中的應用,是繼承思想的發揚光大,後續在研究設計模式的時候要再次加深理解。
9.7 接口中的域
放入接口中的任何域都是 static 和 final 的-->接口可以很方便的管理和創建常量組。
- 接口中定義的域不能使“空 final”的,但是可以被非常量表達式(例如帶有運算符的值)初始化。
- 在接口中的域首次被訪問時,就可以在類第一次被加載的時候初始化。
- 這些域的值被存儲在該接口的靜態存儲區中
9.8 嵌套接口
接口可以嵌套在類或者而其它接口中。
類中嵌套的接口,可以被實現為 private,這樣實現可以強制該接口中的方法定義不要添加任何類型信息(換句話講就是,不允許向上轉型)。
接口中嵌套的接口,作用域接口的各種規則,特別是所有的接口元素都必須是 public 的。
實現某個接口的時候,並不需要實現嵌套在其內部的任何接口,而且 private 接口不能再定義它之外的類被實現。
9.9 接口與工廠
工廠方法設計模式:(純接口實現的工廠方法)
interface Service {
void method1();
void method2();
}
interface ServiceFactory {
Service getService();
}
class Implementation1 implements Service {
Implementation1() {} // Package access
@Override
public void method1() {print("Implementation1 method1");}
@Override
public void method2() {print("Implementation1 method2");}
}
class Implementation1Factory implements ServiceFactory {
@Override
public Service getService() {
return new Implementation1();
}
}
class Implementation2 implements Service {
Implementation2() {} // Package access
@Override
public void method1() {print("Implementation2 method1");}
@Override
public void method2() {print("Implementation2 method2");}
}
class Implementation2Factory implements ServiceFactory {
@Override
public Service getService() {
return new Implementation2();
}
}
public class Factories {
public static void serviceConsumer(ServiceFactory fact) {
Service s = fact.getService();
s.method1();
s.method2();
}
public static void main(String[] args) {
serviceConsumer(new Implementation1Factory());
// Implementations are completely interchangeable:
serviceConsumer(new Implementation2Factory());
}
}
輸出:
Implementation1 method1
Implementation1 method2
Implementation2 method1
Implementation2 method2
【Java編程思想】9.接口