1.第九章一上來就說了接口的作用:接口與內部類為我們提供一種將接口與實現分離的更加結構化的方法。所以這一句的重點我認為就是將抽象與實現分離開來,從而讓代碼更加靈活。
2.再講接口之前書中先講了抽象類,書中說到:包含抽象方法的類叫做抽象類。后面又提到,抽象類中也可以沒有抽象方法,那么這種抽象類的意義只是防止別人創建它的實例,所以其實可以這么理解,用 abstract 修飾的類就是抽象類。
3.上面提到了抽象方法,那我們來看看什么是抽象方法:
// 抽象方法是一種不完整的方法,因為它只有方法聲明沒有方法體,
// 并通過 absrtact 修飾
absrtact void absrtactMethod();
4.我們看到了抽象方法其實不完整就使得擁有該方法的類也是不完整的,所以書中說到:包含抽象方法的類叫做抽象類。如果某個類繼承自它,那么就只存在兩種可能性:一是實現該抽象類中所有抽象方法,二是實現部分或者不實現任何抽象方法,那么第二種情況就使得這個實現了抽象類的類也變成了一個不完整的類,也就是抽象類,這么說有點繞口,簡單地說實現了某個抽象類不實現抽象方法那么這個類就也是抽象的,需要在 class 前用 absrtact 修飾。
5.抽象類和抽象方法非常有用,因為它們可以使類的抽象性明確起來,我的理解是說一個類如果繼承自抽象類,且自身想成為一個普通的類,那么就必須實現抽象類中的所有抽象方法,這點是非常明確的,因為這個類知道了自己一定要去實現哪些方法。
5.本章的名字是接口,下面我們就來著重介紹一下接口,一個接口表示:「所有實現了該特定接口的類看起來都像是這樣。」,所以人們在討論接口的時候都會這么說它,它是暴露在外部的規則。
6.引入 interface 關鍵字替換掉 class 也就可以產生一個極度抽象的類,而同時接口一個十分關鍵的作用,那就是來實現某種類似多重繼承變種的特性,我們都知道 Java 中只能繼承一個類,也就是所謂的單繼承,而引入接口后我們通過 implement 可以實現多個接口,實現類可以向上轉型為接口,就顯得該實現類可以同時向上轉型為多個類,從而拓展了 Java 的單繼承原則。
7.接口的使用我就不舉例子了,我們來說說接口內部的特性,接口中可以包含方法也可以包含屬性,方法默認的被 public 和 abstract 修飾,屬性默認的被 static 和 final 修飾。
interface Instrument {
// static & final
int VALUE = 5;
// public & abstract
void play();
}
8.接口不僅僅只是一種更純粹形式的抽象類,它還有更高的目標:實現類似 C++ 中中的多重繼承。
9.書中提到使用接口的核心原因是,為了能夠向上轉型為多個基類型(以及由此帶來的靈活性)。次要原因與抽象類相同,防止外界創建對象。
10.使用接口還是使用抽象類?書中給出了這樣的回答:如果要創建不帶任何方法定義和成員變量的基類,那么就應該選擇接口,而不是抽象類。事實上,如果知道某事物應該成為一個基類,那么第一選擇應該是使它成為一個接口。
11.類與類之間是繼承關系,類與接口之間是實現關系,而接口與接口之間又是繼承關系,我們可以通過繼承某一個或某幾個接口,從而拓展當前接口的功能。
interface Monster {
void menace();
}
interface Lethal {
void kill();
}
interface Vampire extends Monster, Lethal {
void drinkBlood();
}
class VeryBadVamprice implement Vampire {
public void menace() {}
public void kill() {}
public void drinkBlood() {}
}
12.接口最吸引人的地方就是允許一個接口可以具有多個不同的具體實現,而接口的一種常見的用法就是策略模式。策略模式的定義是這樣的:策略模式定義了一系列的算法,并將每個算法封裝起來,而且使它們可以相互替換。這里實際就是抽取出一個算法接口,然后實現不同的算法,我只要定義一個接收算法接口的作為參數方法就可以了,調用該方法時只要傳遞不同的算法實現就可以了,這里也運用到了開閉原則和里氏替換原則。
13.借用本章總結的最后一句話,恰當的原則應該是優先選擇類而不是接口。借口是一種很重要的工具,但是它們容易被濫用。