多態:同一個符號在不同語義環境下具有不同的解釋
一、多態是通過
1、接口和實現接口並覆蓋接口中同一個方法的幾種不同的類體現的。
2、父類和繼承父類並覆蓋父類中同一方法的幾個不同子類實現的。
二、基本概念
多態性:發送消息給某個對象,讓該對象自己決定響應何種行爲。
通過將子類對象引用賦值給超類對象引用變量來實現動態方法調用。
java的這種機制遵循一個原則:當超類對象引用子類對象時,被引用對象的類型而不是引用變量的類型決定了調用誰的成員方法,但是這個被調用的方法必須是在超類中定義過的,也就是說被子類覆蓋的方法。
1、如果a是類A的一個引用,那麼a可以指向類A的一個實例,或者說指向類A的一個子類。
2、如果a是接口A的一個引用,那麼a必須指向實現了接口A的一個類的實例。
三、多態的分類
1.強制的:一種隱式做類型轉換的方法。
強制多態隱式的將參數按某種方法,轉換成編譯器認爲正確的類型以避免錯誤。在一下的表達式中,編譯器必須決定二元運算符‘+’所應做的工作:
int a = 1 + 2;
double d = 2.0 + 2.0;
String s = "abc" + "def";
2.方法的重載:將一個標誌符用作多個意義。
重載允許用相同的運算符或方法,去表示截然不同的意義。‘+’在上面的程序中有幾個不同意思:兩個int型相加;兩個double型相加;兩個串相連。另外還有整型相加,長整型,等等。這些運算符的重載,依賴於編譯器根據上下文做出的選擇。以往的編譯器會把操作數隱式轉換爲完全符合操作數的類型。雖然Java明確支持重載,但不支持用戶定義的操作符重載。
Java支持用戶定義的函數重載。一個類中可以有相同名字的方法,這些方法可以有不同的意義。這些重載的方法中,必須滿足參數數目不同,相同位上的參數類型不同。這些方法可以幫助編譯器區分不同版本的方法。
編譯器以這種唯一表示的特徵來表示不同的方法,比用名字表示更爲有效。據此,所有的多態行爲都能編譯通過。
強制和重載的多態都被分類爲特定的多態,因爲這些多態都是在特定的意義上的。這些被劃入多態的特性給程序員帶來了很大的方便。強制多態排除了麻煩的類型和編譯錯誤。重載多態像一塊糖,運行程序員用相同的名字表示不同的方法,很方便。
public class One {
//方法體
}
public class Two extends One {
//方法體
}
public class A {
public void f() {
//方法體
}
public void f(int i) {
//方法體
}
public viod f(One one) {
//方法體
}
public One f() {
//方法體
}
}
A a = new A();
a.f();
a.f(1);
3.方法的重寫
發生在父類與子類中,在子類中重寫了父類/超類中的同名方法,在調用子類的該同名方法時父類中的同名方法被“屏蔽”,重寫子類與父類有相同的方法名參數列表(類型、個數、順序)和返回類型(子類重寫的方法的返回類型相同或者是父類返回值的子類)
public class B extends A {
public void f() {...}
public void f(int j) {...} //重寫
public void f(Two two) {...} //不是重寫
public Two f() {...} //重寫
}
4、向上轉型
子類自有的方法不可見
1)、代碼檢查不允許。
2)、從實際意義上
A a = new B();
a.f(); //調用子類的f()方法
a.f(new Two()); //編譯錯誤(定義一個A類引用,JVM解釋a.f(new Two())方法時,A類沒有這個方法)
5、向下轉型
存在於繼承中,父類引用指向的對象實際是要轉型的子類引用的類型。
1) Animal a = new Dog();
Dog d = (Dog) a; //正確
2) Animal a = new Cat();
Dog d = (Dog) a; //拋異常