1.第八章一開頭就說了多態(tài)的作用:消除類型之間的耦合關系。
2.多態(tài)的前提是繼承與重寫,因為繼承之后允許將子類視為自己本身或者當做其父類進行處理,當做其父類處理就涉及到了一個概念向上轉型,而多個子類對其父類的某個方法重寫,并將這些子類向上轉型為父類,就使得父類持有不同子類的引用后再調(diào)用同一方法就能表現(xiàn)出不同的行為。
// Dog & Cat 均繼承自 Animal 并已經(jīng)重寫過yell方法,即不同動物叫聲也不同
Animal animal = new Dog();
animal.yell();
// animal 先持有狗的引用,調(diào)用重寫后的叫聲方法,輸出為 汪汪
animal = new Cat();
animal.yell();
// animal 再持有貓的引用,調(diào)用重寫后的叫聲方法,輸出為 喵~
3.向上轉型:對某個對象的引用視為對其基類的引用。
// Dog 繼承自 Animal
Animal animal = new Dog();
4.子類不可能比父類更“小”,因為繼承那一刻就已經(jīng)獲取父類除了 private 之外的所有內(nèi)容,而且還有個可能添加屬于自己的獨有功能。
5.多態(tài)也被成為動態(tài)綁定,后期綁定,運行時綁定。即通過某種機制,可以在運行時判斷對象的類型,從而調(diào)用恰當?shù)姆椒ā?/p>
6.Java 除了 static 方法和 final 方法(private 方法屬于 final 方法)之外, 其他所有方法都是動態(tài)綁定的,所以 final 關鍵是修飾方法其實也是有效的“關閉”了動態(tài)綁定。
7.為什么說多態(tài)是一項“將改變的事物與未變的事物分離開來”的重要技術,因為我們通過繼承,向上轉向,重寫需要的方法,從而不斷的拓展我的使用,未變的事物指的是基類,而改變的事物就是不斷新拓展出來的之類,從而使得我在不改變的原有代碼的基礎上就可以實現(xiàn)新的功能,只需要我把子類引用賦給父類即可,這也是開閉原則和里氏替換原則的使用。
// 任何 Animal 子類都可以當做參數(shù)傳遞進來
public void animalYell(Animal animal) {
animal.yell();
}
animalYell(new Dog());
animalYell(new Cat());
8.只有非 private 方法才可以被覆蓋。雖然我們可以在子類中定義與基類中 private 方法同名的方法,但這并不是重寫。
9.靜態(tài)方法是與類,而非與單個對象相關聯(lián)的。
10.構造并不具有多態(tài)性,因為他們實際上是 static 的,只不過該 static 的聲明是隱式的。
11.多態(tài)中的構造調(diào)用順序是基類構造總是在導出類之前被調(diào)用,且按照繼承層次組件向上,從而使得背個基類的構造都得到調(diào)用。
12.構造內(nèi)使用多態(tài)的行為。
// 書中的例子
class Glyph {
void draw() {print("Glyph.draw()");}
Glyph() {
print("Glyph() before draw");
draw();
print("Glyph() after draw");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph (int r) {
radius = r;
print("RoundGlyph.RoundGlyph(), radius = " + radius);
}
void draw() {
print("RoundGlyph.draw(), radius = " + radius);
}
}
new RoundGlyph(5);
// 輸出結果如下
Glyph() before draw
// 這時候子類的radius還未獲取到傳遞過來的值
RoundGlyph.draw(), radius = 0
Glyph() after draw
RoundGlyph.RoundGlyph(), radius = 5
13.如果多態(tài),字段看左邊(看基類),方法看右邊(看具體實現(xiàn)類)。
14.所以多態(tài)意味著“不同的形式”,即通過繼承,向上轉型,方法重寫,不同的實現(xiàn)類會體現(xiàn)會不同的形式,從而通過基類調(diào)用同一方法,使得我們只是調(diào)用了基類的方法卻看到了不同形式的結果。
15.向上轉型會丟失具體的類型信息,如果我們可以通過向下轉型從而再次獲得一個的具體信息。