❶ 子類繼承父類怎麼在父類的方法中訪問子類的變數
這是「動態綁定」,動態綁定是指在執行期間(非編譯期)判斷所引用對象的實際類型,根據其實際的類型調用其相應的方法。
而想實現「動態綁定」,必須有繼承、重寫且父類引用指向子類對象,滿足了這3條就屬於「動態綁定」,而它的好處就是像你說的那樣,父類引用訪問的是子類對象的方法,你看下邊的例子吧:
publicclassA
{
publicstaticvoidmain(Stringargs[])
{
Aa=newB();
print(ainstanceofA);
print(ainstanceofB);
a.sayHello();
a=newC();
print(ainstanceofA);
print(ainstanceofC);
a.sayHello();
}
voidsayHello()
{
print("Hello!");
}
publicstaticvoidprint(Objectobj)
{
System.out.println(obj);
}
publicstaticvoidprint()
{
System.out.println();
}
}
classBextendsA
{
voidsayHello()
{
print("Hello,I'mB!");
}
}
classCextendsA
{
voidsayHello()
{
print("Hello,I'mC!");
}
}
它的輸出結果是:
而不是輸出的「Hello」,從輸出的2個true可以看出這里採用的就是「父類引用指向子類對象」,你先別問為什麼輸出的不是「Hello」,其實實際情況也正是我們希望輸出「Hello,I'm B」要好一些,因為我們new的是A類的子類B和C,雖然它們2個都可以直接採用a.sayHello來調用,但如果輸出2個「Hello」,那跟我們直接new一個A類的對象沒什麼區別。如果我們要想不管A有多少子類,都採用a.sayHello來調用(好記、易寫、易改),且java沒有「動態綁定機制」,那麼父類A的sayHello方法可就不好寫了,得先判斷是哪個子類,再調用相關子類的sayHello方法,這跟不採用繼承,直接new個B和C的對象,再採用b.sayHello、c.sayHello沒什麼2樣,那麼這里的「繼承」將毫無意義,而且如果日後你你還需要加一個子類D,你還需要new個D的對象,再採用d.sayHello。
順便,這里你應該還看到了我的父類A還自定義了一個print方法,它的參數既不是String也不是int、double,而是String類、int的包裝類、double的包裝類等類的父類對象Object類,所以我的sayHello方法里給print函數傳遞的是String類(父類Object的引用指向子類對象String類),而main方法里的print(a instanceof A)語句傳遞的是boolean的包裝類(父類Object的引用指向子類對象Boolean類),所以這2種調用也是用了「動態綁定」,如果不用呢?不是很多新手都希望java能像C那樣直接print("Hello World")多好,那麼如果不用「動態綁定」,光是8個基本類型你就需要重寫8個print函數,而且,System.out.println語句傳遞的參數個數也是不確定的(盡管最後都連接成1個String參數),你不用「動態綁定」如何重寫?你寫不出來!
再舉個例子,如果你寫了一個小游戲,幾十中坦克都繼承於同一個父類:Tank類,然後,你想在游戲界面新建1個坦克,那你的main方法只需要統統採用類似於a.Draw()的語句去畫一個坦克即可(全用父類對象的引用),而不需要先判斷是哪個子類,再採用類似【case b:b.Draw();break;case c:c.Draw();break;……case n:n.Draw();break;】的語句(幾十、幾百個子類,你光判斷語句恐怕就幾百行了吧?),同樣開火、移動都只需要調用a.Fire()、a.up()、a.down()、a.Left()、a.Right()即可。而且,如果日後你再想新加1個叫Tank99的子類,那麼你的主方法里關於生成一輛Tank99坦克和Tank99的開火、移動等一系列語句都無需修改,你只需要寫一個Tank99類,繼承並重寫Tank父類的方法即可(你不採用「動態綁定」,那麼主方法里的一切相關方法全部都需要修改,忘了1個地方,程序就出錯了)。程序的可擴展性和健壯性很好,這就是java中「動態綁定機制」的好處。
❷ 請問子類中繼承過來的公有函數,可以訪問基類的私有成員變數嗎
不可以。
可以和慎明先看下C++的繼承機制,在計運算元類對象所佔內存大小的時候,父類的私有成員變數大小也計算在內。所以,子喚告類繼承父類時,內部包含父類孝攜的私有成員,只不過是已經固化且不可見的。繼承自父類的私有成員變數,子類不可見,不可另加操作,實例化後與父類對象私有成員所佔內存區地址不同。
當父類存在共有或保護函數對其私有成員變數操作時,子類也可使用繼承自父類的這些函數對其內部隱藏的同樣繼承自父類的私有成員變數進行操作。但子類無法再寫一個函數對這部分成員變數進行訪問或修改。
❸ java繼承之後父類構造函數訪問子類變數的問題
這個。。。是編譯錯誤吧?
翻譯過來也不是超類型調用之前無法引用s
而是在調用構造函數時,不能訪問s
我的理解是這樣,s沒有加static的修飾符,他就是一個實例變數,畢滑要先有實例才能使用的變數。實例是構造函數執行完之後才產生的。
而加上static之後就不會報錯,原因是static是類變數,不需要實例裂做就可以使用。
這是我的看法,你要是有什麼不同意見可以說出來一起討論討論手源臘。。。
❹ C#中類的私有變數能被繼承嗎若能被繼承,那麼private修飾的變數只能在它所屬的類中被訪問時怎麼回事
一個類中的私有(private)變數是不能被繼承的,不能被其他的類調用。
之所以不能被繼承和不能被其它類調用是為了不讓用戶直接去操作這個對象,也就是說為了數據安全性。
例如:電冰箱上面調溫度的按鈕,如果給用戶直接操作,那溫度顯示可以是任何數字(但是沒那個溫度)
所以出現了封裝(隱藏內部的實現,提供外部介面),
代碼:
private
int
number;
public
int
Number
{
get{return
number;}
set{this.number=value;}
}
在另一個類里要調用number(實際上的調用不到的),調用Number就可以了,同樣賦值給Number就是賦值給number,同樣可以設置你能調用和賦值的范圍。這樣用戶就不能把空調溫度調到-100。
也許你會有這樣的想法,直接寫一個公共(public)的,然後設置它的取值賦值的范圍還不是一樣。肯定的回答:不一樣。如果一個大型的程序的一千個類都要用到number你是不是要重復寫一千個number,那樣在棧中開辟的空間太多,太浪費內存。而且大部分類所賦的值和去的值都不能,那你寫了一個固定的值有什麼用。