1.第九章一上來(lái)就說(shuō)了接口的作用:接口與內(nèi)部類為我們提供一種將接口與實(shí)現(xiàn)分離的更加結(jié)構(gòu)化的方法。所以這一句的重點(diǎn)我認(rèn)為就是將抽象與實(shí)現(xiàn)分離開來(lái),從而讓代碼更加靈活。
2.再講接口之前書中先講了抽象類,書中說(shuō)到:包含抽象方法的類叫做抽象類。后面又提到,抽象類中也可以沒(méi)有抽象方法,那么這種抽象類的意義只是防止別人創(chuàng)建它的實(shí)例,所以其實(shí)可以這么理解,用 abstract 修飾的類就是抽象類。
3.上面提到了抽象方法,那我們來(lái)看看什么是抽象方法:
// 抽象方法是一種不完整的方法,因?yàn)樗挥蟹椒暶鳑](méi)有方法體,
// 并通過(guò) absrtact 修飾
absrtact void absrtactMethod();
4.我們看到了抽象方法其實(shí)不完整就使得擁有該方法的類也是不完整的,所以書中說(shuō)到:包含抽象方法的類叫做抽象類。如果某個(gè)類繼承自它,那么就只存在兩種可能性:一是實(shí)現(xiàn)該抽象類中所有抽象方法,二是實(shí)現(xiàn)部分或者不實(shí)現(xiàn)任何抽象方法,那么第二種情況就使得這個(gè)實(shí)現(xiàn)了抽象類的類也變成了一個(gè)不完整的類,也就是抽象類,這么說(shuō)有點(diǎn)繞口,簡(jiǎn)單地說(shuō)實(shí)現(xiàn)了某個(gè)抽象類不實(shí)現(xiàn)抽象方法那么這個(gè)類就也是抽象的,需要在 class 前用 absrtact 修飾。
5.抽象類和抽象方法非常有用,因?yàn)樗鼈兛梢允诡惖某橄笮悦鞔_起來(lái),我的理解是說(shuō)一個(gè)類如果繼承自抽象類,且自身想成為一個(gè)普通的類,那么就必須實(shí)現(xiàn)抽象類中的所有抽象方法,這點(diǎn)是非常明確的,因?yàn)檫@個(gè)類知道了自己一定要去實(shí)現(xiàn)哪些方法。
5.本章的名字是接口,下面我們就來(lái)著重介紹一下接口,一個(gè)接口表示:「所有實(shí)現(xiàn)了該特定接口的類看起來(lái)都像是這樣。」,所以人們?cè)谟懻摻涌诘臅r(shí)候都會(huì)這么說(shuō)它,它是暴露在外部的規(guī)則。
6.引入 interface 關(guān)鍵字替換掉 class 也就可以產(chǎn)生一個(gè)極度抽象的類,而同時(shí)接口一個(gè)十分關(guān)鍵的作用,那就是來(lái)實(shí)現(xiàn)某種類似多重繼承變種的特性,我們都知道 Java 中只能繼承一個(gè)類,也就是所謂的單繼承,而引入接口后我們通過(guò) implement 可以實(shí)現(xiàn)多個(gè)接口,實(shí)現(xiàn)類可以向上轉(zhuǎn)型為接口,就顯得該實(shí)現(xiàn)類可以同時(shí)向上轉(zhuǎn)型為多個(gè)類,從而拓展了 Java 的單繼承原則。
7.接口的使用我就不舉例子了,我們來(lái)說(shuō)說(shuō)接口內(nèi)部的特性,接口中可以包含方法也可以包含屬性,方法默認(rèn)的被 public 和 abstract 修飾,屬性默認(rèn)的被 static 和 final 修飾。
interface Instrument {
// static & final
int VALUE = 5;
// public & abstract
void play();
}
8.接口不僅僅只是一種更純粹形式的抽象類,它還有更高的目標(biāo):實(shí)現(xiàn)類似 C++ 中中的多重繼承。
9.書中提到使用接口的核心原因是,為了能夠向上轉(zhuǎn)型為多個(gè)基類型(以及由此帶來(lái)的靈活性)。次要原因與抽象類相同,防止外界創(chuàng)建對(duì)象。
10.使用接口還是使用抽象類?書中給出了這樣的回答:如果要?jiǎng)?chuàng)建不帶任何方法定義和成員變量的基類,那么就應(yīng)該選擇接口,而不是抽象類。事實(shí)上,如果知道某事物應(yīng)該成為一個(gè)基類,那么第一選擇應(yīng)該是使它成為一個(gè)接口。
11.類與類之間是繼承關(guān)系,類與接口之間是實(shí)現(xiàn)關(guān)系,而接口與接口之間又是繼承關(guān)系,我們可以通過(guò)繼承某一個(gè)或某幾個(gè)接口,從而拓展當(dāng)前接口的功能。
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.接口最吸引人的地方就是允許一個(gè)接口可以具有多個(gè)不同的具體實(shí)現(xiàn),而接口的一種常見的用法就是策略模式。策略模式的定義是這樣的:策略模式定義了一系列的算法,并將每個(gè)算法封裝起來(lái),而且使它們可以相互替換。這里實(shí)際就是抽取出一個(gè)算法接口,然后實(shí)現(xiàn)不同的算法,我只要定義一個(gè)接收算法接口的作為參數(shù)方法就可以了,調(diào)用該方法時(shí)只要傳遞不同的算法實(shí)現(xiàn)就可以了,這里也運(yùn)用到了開閉原則和里氏替換原則。
13.借用本章總結(jié)的最后一句話,恰當(dāng)?shù)脑瓌t應(yīng)該是優(yōu)先選擇類而不是接口。借口是一種很重要的工具,但是它們?nèi)菀妆粸E用。