1. 程式人生 > >Java 中的多態

Java 中的多態

animal col n) 編譯 spa his 條件 父類引用 size

java多態,如何理解父類引用指向子類對象

要理解多態性,首先要知道什麽是“向上轉型”。

我定義了一個子類Cat,它繼承了Animal類,那麽後者就是前者是父類。我可以通過 Cat c = new Cat(); 實例化一個Cat的對象,這個不難理解。

但當我這樣定義時: Animal a = new Cat();

表示定義了一個Animal類型的引用,指向新建的Cat類型的對象。由於Cat是繼承自它的父類Animal,所以Animal類型的引用是可以指向Cat類型的對象的。

那麽這樣做有什麽意義呢?因為子類是對父類的一個改進和擴充,所以一般子類在功能上較父類更強大,屬性較父類更獨特, 定義一個父類類型的引用指向一個子類的對象既可以使用子類強大的功能,又可以抽取父類的共性。

所以,父類類型的引用可以調用父類中定義的所有屬性和方法,而對於子類中定義而父類中沒有的方法,它是無可奈何的; 同時,父類中的一個方法只有在父類中定義而在子類中沒有重寫的情況下,才可以被父類類型的引用調用; 對於父類中定義的方法,如果子類中重寫了該方法,那麽父類類型的引用將會調用子類中的這個方法,這就是動態連接。也可以叫做動態綁定。

動態綁定是指”在執行期間(而非編譯期間)“判斷所引用對象的實際類型,根據實際的類型調用其相應的方法。

看下面這段程序:

class Father {
public void func1()

{
func2();


}

// 這是父類中的func2()方法,因為下面的子類中重寫了該方法 ,所以在父類類型的引用中調用時,這個方法將不再有效,取而代之的是將調用子類中重寫的func2()方法


public void func2() {
System.out.println("AAA");
}
}

class Child extends Father { // func1(int i)是對func1()方法的一個重載


由於在父類中沒有定義這個方法,所以它不能被父類類型的引用調用
所以在下面的main方法中child.func1(68)是不對的


public void func1(int i) {


System.out.println("BBB");
} // func2()重寫了父類Father中的func2()方法 如果父類類型的引用中調用了func2()方法,那麽必然是子類中重寫的這個方法
public void func2() {
System.out.println("CCC");
}
}
public class PolymorphismTest {
public static void main(String[] args) {
Father child = new Child();
child.func1();// 打印結果將會是什麽? } }

上面的程序是個很典型的多態的例子。子類Child繼承了父類Father,並重載了父類的func1()方法,重寫了父類的func2()方法。重載後的 func1(int i)和func1()不再是同一個方法,由於父類中沒有func1(int i),那麽,父類類型的引用child就不能調用func1(int i)方法。而子類重寫了func2()方法,那麽父類類型的引用child在調用該方法時將會調用子類中重寫的func2()
}
}

那麽該程序將會打印出什麽樣的結果呢? 很顯然,應該是“CCC”。

對於多態,可以總結它為:

一、使用父類類型的引用指向子類的對象;

二、該引用只能調用父類中定義的方法和變量;

三、如果子類中重寫了父類中的一個方法,那麽在調用這個方法的時候,將會調用子類中的這個方法;(動態連接、動態調用)

四、變量不能被重寫(覆蓋),”重寫“的概念只針對方法,如果在子類中”重寫“了父類中的變量,那麽在編譯時會報錯。

多態的3個必要條件:

1.繼承 2.重寫 3.父類引用指向子類對象。

——————————————————————

向上轉型: Person p = new Man() ; //向上轉型不需要強制類型轉化
向下轉型: Man man = (Man)new Person() ; //必須強制類型轉化

Java 中的多態