問題的提出:
class Parent {
private void method1() {
System.out.println("Parent's method1()");
}
public void method2() {
System.out.println("Parent's method2()");
method1(); // ①
}
}
class Child extends Parent {
public void method1() {
System.out.println("Child's method1()");
}
public static void main(String args[]){
Parent p = new Child(); // ②
p.method2(); // ③
}
}
在②處聲明了一個Parent類型的引用p,它指向一個Child對象;通常來說,p應該具有後綁定功能。③處調用method2(),這個method2()肯定是指從Parent類繼承而來的method2()。
但問題是Parent類的method2()中,調用了method1(),這個method1()是誰的?Parent的,還是Child的?
看起來挺難判斷的,但結果是調用了Parent的method1()?也許會問method1()不是Parent的一個私人成員嗎?Child對象怎麼能調用呢?
請先看下面的例子,將得到解答——
例子一:
class Base5 {
protected void doStuff1() {
System.out.println("Base-doStuff1");
}
final void doStuff2() {
System.out.println("Base-doStuff2");
}
}
class Child5 extends Base5 {
protected void doStuff1() {
System.out.println("Child-doStuff1");
}
protected void doStuff2() { // ④
System.out.println("Child-doStuff2");
}
public static void main(String[] args) {
Base5 c = new Child5();
c.doStuff1();
c.doStuff2();
}
}
編譯結果如下:
D:/JavaEx/scjp/tst/tst18.java:14: doStuff2() in Child5 cannot override doStuff2() in Base5; overridden method is final
protected void doStuff2() {
^
1 error
由於Base5的doStuff2()是final的,所以④處Child5無法重寫doStuff2(),因此也就不會有後綁定的多態。亦即:父類中final的方法不支援後綁定的多態。
例子二:
class Base5 {
protected void doStuff1() {
System.out.println("Base-doStuff1");
}
private void doStuff2() {
System.out.println("Base-doStuff2");
}
}
class Child5 extends Base5 {
protected void doStuff1() {
System.out.println("Child-doStuff1");
}
protected void doStuff2() {
System.out.println("Child-doStuff2");
}
public static void main(String[] args) {
Base5 c = new Child5();
c.doStuff1();
c.doStuff2();
}
}
編譯結果如下:
D:/JavaEx/scjp/tst/tst18.java:21: doStuff2() has private access in Base5
c.doStuff2();
^
1 error
因為是私人成員,所以c.doStuff2()會產生錯誤,但更重要的是private就相當於final,父類中的final方法不支援後綁定,則private也是如此。亦即:父類中private的方法不支援後綁定的多態。
只有一步之遙
離解答問題只有一步之遙,還得補充一個基本常識。類的成員方法不論是否接受參數,它其實都隱含地接受了一個參數,即this。
何謂this?由《Thinking in Java(3rd Edition)》中:this是對當前對象的一個引用。
回到最初的問題:
class Parent {
private void method1() {
System.out.println("Parent's method1()");
}
public void method2() {
System.out.println("Parent's method2()");
method1(); // ⑤
}
}
class Child extends Parent {
public void method1() {
System.out.println("Child's method1()");
}
public static void main(String args[]){
Parent p = new Child();
p.method2();
}
}
由上一段補充的知識可知⑤處實際上是:
this.method1();
根據例子一和二可知,父類中private的方法不支援後綁定多態,因此它嚴格按照引用的類型來調用對應的方法,因此它調用Parent的method1()。
當把Parent的method1()前的private換成public/protected/friendly(預設),則後綁定將順利完成,自動調用Child的method1()。
總結
父類中final的方法在子類中無法被重寫,因此不會有後綁定多態的問題。
父類中private的方法類似於final,雖然可以被重新定義,但不是重寫。
當出現父類中含有private的方法的後綁定多態問題時,非private方法依然可以根據後綁定對象的實際情況,即時調用對應的方法;而private的方法,不支援此特性,它只根據調用它的參考型別來確定需要調用的方法。
原文地址:http://lslling.blogchina.com/1717345.html