06繼承與多態
繼承與多態動手動腦問題:
public class ParentChildTest {
public static void main(String[] args) {
Parent parent=new Parent();
parent.printValue();
Child child=new Child();
child.printValue();
parent=child;
parent.printValue();
parent.myValue++;
parent.printValue();
((Child)parent).myValue++;//基類對象賦給子類變量要執行強制類型轉換
//語法:子類對象變量=(子類名)基類對象名;如果類型轉換失敗會拋出異常 parent.printValue();
}
}
class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}
1.你的結果是:?
Parent.printValue(),myValue=100
Child.printValue(),myValue=200
Parent.printValue(),myValue=200
Child.printValue(),myValue=201
Child.printValue(),myValue==201
2.程序運行的結果是:
3.你如何解釋會得到這樣的輸出?
第一行和第二行就是直接輸出類中的數值,沒有疑問。
而第三行輸出的是200,原因是:
parent.myValue++相當於parent.myValue+parent.myValue即兩次調用parent的方法,故輸出應該是200
4.計算機是不會出錯的,之所以得到這樣的運行結果也是有原因的,那麽從這些運行結果中,你能總結出Java的哪些語法特性?
當子類與父類擁有一樣的方法,並且讓一個父類變量引用一個子類對象時,到底調用哪個方法,由對象自己的“真實”類型所決定,這就是說:對象是子類型的,它就調用子類型的方法,是父類型的,它就調用父類型的方法。
這個特性實際上就是面向對象“多態”特性的具體表現。
如果子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。如果子類方法確實想訪問父類中被隱藏的同名字段,可以用super關鍵字來訪問它。
如果子類被當作父類使用,則通過子類訪問的字段是父類的!
思考:
為什麽子類的構造方法在運行之前,必須調用父類的構造方法?能不能反過來?為什麽不能反過來?
構造函數是一種特殊的方法,主要用來在創建對象時初始化對象,即為對象成員變量賦初始值,總與new運算符一起使用在創建對象的語句。特別的一個類可以有多個構造函數,可根據其參數個數的不同或參數類型的不同來區分它們,即構造函數的重載。構造函數的主要功能用於在類的對象創建時定義初始化的狀態。
構造一個對象,先調用其構造方法和成員變量。
子類擁有父的成員變量和成員方法,如果不調用,則從父類繼承而來的成員變量和方法得不到正確的初始化。
不能反過來調用也是這個原因,因為父類根本不知道子類有什麽變量而且這樣一來子類也得不到初始化的父類變量,導致程序出錯!
類型轉換
下列語句哪一個將引起編譯錯誤?為什麽?哪一個會引起運行時錯誤?為什麽? m=d; d=m; d=(Dog)m; d=c; c=(Cat)m; 先進行自我判斷,得出結論後,運行TestCast.java實例代碼,看看你的判斷是否正確。
d=m,d=c運行時將會報錯。因為m是父類對象,d是子類對象。將父類對象轉化成子類對象,必須進行強制轉換。而d和c是兩個互不相幹的類對象,所以不能將d賦值給c.
06繼承與多態