java繼承實質、父類引用指向子類對象(多態)、聲明時類型、運行時類型


繼承是面向對象的三大特征(封裝、繼承和多態)之一,也是Java語言的重要特性。

那么,繼承父類的成員變量和繼承父類的方法有什么區別嗎?答案是肯定的。有的人甚至都不知道這個問題的存在。


繼承成員變量和繼承方法的區別:

可能大家都認同 “當子類繼承父類時,子類會獲得父類中定義的成員變量和方法,當訪問權限允許的情況下,子類可以直接訪問父類的變量和方法”的看法。這種觀點其實稍顯籠統,因為java繼承中對成員變量和方法的處理是不同的。示例如下:

class Base{

int count=2;
public void display(){
System.out.println(this.count);
}
}
public class Derived extends Base{


int count=20;

@Override
public void display() {

System.out.println(this.count);
}

public static void main(String[] args) {

//父類引用指向子類對象
Base bd=new Derived();      //注釋1
System.out.println(bd.count);
bd.display();

}


}

輸出結果:

-------------------------------------

2
20

-------------------------------------

如果你剛剛稍微認真分析了代碼,你可能會發現你的預計輸出跟實際輸出是不同的。很可能你會說“不對呀,bd不是指向子類Derived的對象嗎?結果不應該是20嗎?”

其實原因是這樣的:

首先應該知道聲明時類型、運行時類型這兩個概念。前者是說在聲明一個引用變量時用到的類型,后者是指在實際運行中的類型。可能會比較抽象。簡單來說對於Base bd=new Derived();  

Base就是bd的聲明時類型,Derived就是bd的運行時類型。


一個簡單卻重要的結論是:如果子類重寫了父類的方法,那么就會覆蓋父類中被重寫的方法,這時,指向子類對象的引用調用這些父子類都有的方法無論聲明時類型是其父類還是自身,調用的都是子類中重寫后的方法,這叫做覆蓋。而父類的成員變量卻不會被子類中同名的成員變量所覆蓋,當這些同名的實例變量被引用變量訪問時,其返回值取決於引用的聲明時類型。


例如本例中bd的聲明時類型是Base,這時訪問父子類同名的實例變量count的返回值就是Base類中的count值。

bd.display()當然調用的就是運行時類型Derived類中的(如果該方法在子類中被重寫的話,否則調用父類中的)。



轉自:


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com