1. 程式人生 > >03繼承與多型 動手動腦

03繼承與多型 動手動腦

動手實驗:繼承條件下的構造方法呼叫

執行 TestInherits.java 示例,觀察輸出,注意總結父類與子類之間構造方法的呼叫關係修改Parent構造方法的程式碼,顯式呼叫GrandParent的另一個建構函式,注意這句呼叫程式碼是否是第一句,影響重大!

class Grandparent 
{


    public Grandparent()
     {

            System.out.println("GrandParent Created.");
    
}


    public Grandparent(String string) 
    {

            System.out.println(
"GrandParent Created.String:" + string); } } class Parent extends Grandparent { public Parent() { //super("Hello.Grandparent."); System.out.println("Parent Created"); // super("Hello.Grandparent."); } } class Child extends Parent {
public Child() { System.out.println("Child Created"); } } public class TestInherits { public static void main(String args[]) { Child c = new Child(); } }
Testlnherits.java

通過super呼叫基類構造方法,必須是子類構造方法中的第一個語句

 

思索:

為什麼子類的構造方法在執行之前,必須呼叫父類的構造方法?能不能反過來?為什麼不能反過來?

建構函式主要是用來在建立物件時初始化物件,即為物件成員變數賦初值。由於子類是繼承父類的,所以建立子類物件時,必須先呼叫父類的構造方法,這樣子類才能有父類的屬性和方法。不能反過來是因為父類不知道子類有什麼變數,而子類也得不到父類的初始化變數。

 

請自行編寫發程式碼測試一下特性:
在子類中若要呼叫父類中被覆蓋的方法,可以使用super關鍵字

class Parent{
    public void method(){
        System.out.println("這是父類");
    }
}

class Child extends Parent{
    public void method(){
        System.out.println("這是子類");
        super.method();
    }
}

public class Override {
    public static void main(String [] args){
        Child c = new Child();
        c.method();
    }
}
Override.java

執行截圖:

 

程式執行結果是什麼? 你如何解釋會得到這樣的輸出? 計算機是不會出錯的,之所以得 到這樣的執行結果也是有原因的, 那麼從這些執行結果中,你能總結出Java的哪些語法特性?

請務必動腦總結,然後修改或編寫一些程式碼進行測試,驗證自己的想法,最後再看 後面的PPT給出的結論。

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);
    }
}
ParentChildTest.java

執行截圖:

如果子類與父類有相同的欄位,則子類中的欄位會代替或隱藏父類的欄位,子類方法中訪問的是子類中的欄位(而不是父類中的欄位)。如果子類方法確實想訪問父類中被隱藏的同名欄位,可以用super關鍵字來訪問它。如果子類被當作父類使用,則通過子類訪問的欄位是父類的。

當子類與父類擁有一樣的方法,並且讓一個父類變數引用一個子類物件時,物件是子型別的,它就呼叫子型別的方法,是父型別的,它就呼叫父型別的方法。

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+="a";
        parent.printValue();
        System.out.println(parent.myValue);
        
        ((Child)parent).myValue+="b";
        parent.printValue();
        System.out.println(((Child)parent).myValue);
        
    }
}

class Parent{
    public String myValue="這是父類的屬性";
    public void printValue() {
        System.out.println("呼叫父類的方法\t"+myValue);
    }
}
class Child extends Parent{
    public String myValue="這是子類的屬性";
    public void printValue() {
        System.out.println("呼叫子類的方法\t"+myValue);
    }
}
驗證

執行截圖: