java的繼承機制
這次我想深入探究以下java裡類的繼承機制。
我們知道,繼承是java設計裡的一個失敗的地方。高司令說過:如果讓他重新設計java的話,他會把繼承去掉。而java裡繼承到底怎麼了,會這麼不受人歡迎呢?
我們知道,繼承設計的初衷是為了程式碼複用。在C++裡也確實做到了這一點,因為C++允許多重繼承。特別是C++裡的解構函式,申明為了virtual的時候可以多重複用,用起來也很舒服。
那麼為什麼在java裡繼承就這麼讓人詬病呢?
第一:java裡的類不能多重繼承,如果一個類一旦繼承了它的父類,那麼它就別想再繼承別的類。一個兒子只能有一個老爸,原本設計是沒錯的。可是在實際應用中,就會出現各種問題。
第二:java裡有更好的介面,介面從本質上來說可以更好的代替繼承。實現像C++裡一樣的巨集定義的功能,把你想要的東西都抽象在介面裡,讓具體的類去實現這些功能。
如果你去面試過,肯定遇到過不少考察java繼承機制的題目,其中最顯著的一個就是建構函式的呼叫和重寫方法的呼叫。
這裡我再強調一下過載和重寫:
過載是同一個類裡面相同方法名,不同引數型別或個數的方法。這也是C++類裡面為什麼出現函式模板的原因,就拿求和來說:
int add(int a,int b);
long add(long a,long b);
int main(){
}
因為求和可能是求int的和,也可能是求long的和,這個時候就出現了需求(我始終認為,一種東西的出現必定是因為對他的需求)
而重寫呢,就是子類對父類裡的方法的重改,就是他改寫了父類的方法。倫理上看似不孝,而道理上是事物總是要不斷髮展的。這就像是社會的改革一樣。
下面我來分析一下父類和子類的建構函式呼叫順序:
在記憶體機制中,父類和子類是佔用同一塊記憶體的,只不過子類在父類的基礎上增加了自己的部分(包括資料成員和屬性),這樣一來就好理解了。子類是依附於父類的,先有父類再有子類。所以說一個子類物件的產生,必須先呼叫父類的建構函式產生一個父類例項,然後在這個例項基礎上新增自己的部分。
而實際的執行機制,也正是這樣的。
因為這樣就很容易理解了,先呼叫父類的建構函式,再呼叫子類的建構函式。
而對於父類和子類裡重寫的方法的呼叫,關鍵要看:子類到底是否產生,如果子類產生了,子類改寫了父類的方法,看似父類和子類各自有一個方法,其實它們在記憶體模型裡佔用的是同一塊記憶體,子類方法會覆蓋父類方法。
我們看下面的程式:
class SuperStringTest {
SuperStringTest(){
System.out.println("Father is constructed.");
}
public void test(){
System.out.println("Father is running.");
}
}
public class StringTest extends SuperStringTest{
StringTest(){
System.out.println("Son is constructed.");
}
public void test(){
System.out.println("Son is running.");
}
public static void main(String[] args){
/*
SuperStringTest sst = new StringTest();
此時,派生類的方法覆蓋了基類的方法,基類的方法對派生類來說為不可見(有先像作用域),也就是派生類裡的同名方法重新寫了基類的同名方法。此時,對基類和派生類來說只有被派生類改寫後的唯一的一個方法。所以,只能呼叫派生類的方法。
Father is constructed.
Son is constructed.
Son is running.
*/
/*
StringTest sst = new StringTest();
解釋同上面
Father is constructed.
Son is constructed.
Son is running.
*/
/*
SuperStringTest sst = new SuperStringTest();
此時,基類所佔的記憶體單元中並沒有派生類的東西。所以,方法沒被改寫,呼叫父類的方法。
Father is constructed.
Father is running.
*/
sst.test();
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=640253
相關文章
- C++的核心特性:繼承機制C++繼承
- 【機制】JavaScript的原型、原型鏈、繼承JavaScript原型繼承
- Java的繼承Java繼承
- 探索 React 中 es6 的繼承機制React繼承
- java中的繼承Java繼承
- 12.16 Java繼承Java繼承
- java繼承extendsJava繼承
- ES5和ES6及繼承機制繼承
- 深入瞭解JavaScript中基於原型(prototype)的繼承機制JavaScript原型繼承
- Java集合繼承圖Java繼承
- java -繼承 -重寫Java繼承
- Java繼承練習Java繼承
- odoo 繼承(owl繼承、web繼承、view繼承)Odoo繼承WebView
- 原型鏈的繼承機制及其背後的程式設計哲學原型繼承程式設計
- Javascript繼承4:潔淨的繼承者—-原型式繼承JavaScript繼承原型
- java繼承與多型Java繼承多型
- 【Java】繼承、抽象、組合Java繼承抽象
- Java 繼承是什麼?Java繼承
- java物件導向繼承Java物件繼承
- 菱形繼承,虛繼承繼承
- 原型,繼承——原型繼承原型繼承
- C++中公有繼承、保護繼承、私有繼承的區別C++繼承
- Java中介面與繼承的區別Java繼承
- Java中的類繼承與多型Java繼承多型
- JAVA中的註解可以繼承嗎?Java繼承
- 類的繼承_子類繼承父類繼承
- java——繼承遇到構造方法Java繼承構造方法
- java繼承基礎詳解Java繼承
- Java之繼承和抽象類Java繼承抽象
- 多繼承 與 多重繼承繼承
- Javascript繼承2:建立即繼承—-建構函式繼承JavaScript繼承函式
- Java類是如何預設繼承Object的?Java繼承Object
- Java建構函式的繼承問題Java函式繼承
- 學習Java中遇到的繼承問題Java繼承
- 類的繼承繼承
- Pyhon的繼承繼承
- Java入門系列-16-繼承Java繼承
- Java核心技術筆記 繼承Java筆記繼承
- Java 自學 - 介面與繼承 介面Java繼承