1. 動(dòng)態(tài)綁定
若子類SubClass覆蓋了父類SuperClass的某個(gè)非final非private方法f1()
即使子類被聲明為
SuperClass child = new SubClass();
使用child.f1()時(shí)仍然訪問子類的f1()
2. 如果把某個(gè)方法聲明為final,可以防止其他人覆蓋該方法。更為重要的一點(diǎn)是,這樣做可以有效的關(guān)閉動(dòng)態(tài)綁定,從而生成更有效的代碼。然而,大多數(shù)情況下,這樣做對(duì)程序的整體性能不會(huì)有什么改觀。因此并不提倡為了僅僅提高性能而使用final。
3. private方法無法被覆蓋,但還是要注意覆蓋private方法的現(xiàn)象,上面的例子中,如SuperClass中含有private方法f2(),而子類中也聲明了同名的方法f2(),子類被聲明為
SuperClass child = new SubClass();
child.f2()時(shí)訪問了父類的f2()
4. 構(gòu)造器和多態(tài)
構(gòu)造器基本順序:
1)調(diào)用基類構(gòu)造器(遞歸過程)
2)按聲明順序調(diào)用成員的初始化方法。
3)調(diào)用導(dǎo)出類構(gòu)造器的主體。
5. 繼承與清理
通過組合與京城方法來創(chuàng)建新類時(shí),不必?fù)?dān)心對(duì)象的清理問題。如果確實(shí)遇到清理的問題,那么必須為新類創(chuàng)建dispose()方法。當(dāng)覆蓋被繼承類的dispose()方法時(shí),務(wù)必記住調(diào)用基類的dispose()方法,也要注意清理順序。
6. 構(gòu)造器內(nèi)部的多態(tài)方法的行為
如果要調(diào)用構(gòu)造器內(nèi)部的一個(gè)動(dòng)態(tài)綁定的方法,就要用到那個(gè)方法的被覆蓋后的定義。然而,產(chǎn)生的效果可能相當(dāng)難于預(yù)料,并且可能造成一些難于發(fā)現(xiàn)的隱藏錯(cuò)誤。
在任何構(gòu)造器的內(nèi)部,整個(gè)對(duì)象可能只是部分形成,然而一個(gè)動(dòng)態(tài)綁定的方法調(diào)用卻會(huì)向外深入到繼承層次結(jié)構(gòu)內(nèi)部,它可以調(diào)用導(dǎo)出類的方法。如果在構(gòu)造器里這么做,那么就可能會(huì)調(diào)用某個(gè)方法,而這個(gè)方法所操縱的成員可能還未初始化--這肯定會(huì)出問題。
import com.bruceeckel.simpletest.*;
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}
class RoundGlyph extends Glyph {
private int radius = 1;
RoundGlyph(int r) {
radius = r;
System.out.println(
"RoundGlyph.RoundGlyph(), radius = " + radius);
}
void draw() {
System.out.println(
"RoundGlyph.draw(), radius = " + radius);
}
}
public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
最后顯示
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
實(shí)際應(yīng)用中,或許這會(huì)導(dǎo)致RoundGlyph對(duì)象生成后只畫了一個(gè)點(diǎn),而不是預(yù)期的半徑為1的圓。
解釋:初始化的實(shí)際過程是:
1)將分配給對(duì)象的儲(chǔ)存空間初始化為二進(jìn)制的0。
2)調(diào)用基類構(gòu)造器。即此時(shí)調(diào)用了draw()方法,但radius仍然為0。
3)按照聲明的順序調(diào)用成員的初始化方法。
4)調(diào)用導(dǎo)出類的構(gòu)造器主體。
邏輯方法已經(jīng)十分完美,但行為卻會(huì)出錯(cuò)(這種情況下,C++會(huì)產(chǎn)生更合理的行為)
因此,編寫構(gòu)造器有一條有效的準(zhǔn)則:用盡可能簡(jiǎn)單的方法使對(duì)象進(jìn)入正常狀態(tài);如果可以的話,避免調(diào)用其他方法。在構(gòu)造器內(nèi)唯一能夠安全調(diào)用的那些方法是基類中的final方法(包括private方法),這些方法不能被覆蓋,也就不會(huì)出現(xiàn)上述問題。
7. 依然是繼承/組合的選擇
一條通用的準(zhǔn)則是,用繼承表達(dá)行為間的差異,用字段表達(dá)狀態(tài)上的變化。
8. 純繼承:只有在基類或接口中已經(jīng)建立的方法才可以在導(dǎo)出類中被覆蓋,基類與導(dǎo)出類的接口相同。
9. 向下轉(zhuǎn)型