摘要:多態性面向對象三大特性封裝繼承多態。面向對象多態性存在的三個必要條件繼承重寫父類引用指向子類對象多態性的實現方式重寫與重載靜態多態性方法重載方法重載允許類具有多個相同名稱的方法,但是方法參數列表不同。
多態性
面向對象(OOP)三大特性:封裝、繼承、多態。
多態性(polymorphism)指同一行為具有多種不同表現形式,在面向對象程序設計中表現為同一消息可以根據發送對象的類型不同,做出多種不同的行為。
多態性的優點
多態性能夠從一定程度上消除類型之間的耦合關系,通過統一接口方式,不同類的對象可以直接替換,程序更加靈活,可擴展。
面向對象多態性存在的三個必要條件
繼承
重寫
父類引用指向子類對象
多態性的實現方式 重寫(Override)與重載(Overload) 靜態多態性:方法重載(Method Overloading)方法重載(Method Overloading)允許類具有多個相同名稱的方法,但是方法參數列表不同。
重載形式:
case 1: 參數數量變化(有效)
add(int, int) add(int, int, int)
case 2: 參數數據類型變化(有效)
add(int, int) add(int, float)
case 3: 參數數據類型順序變化(有效)
add(int, float) add(float, int)
bad case 1: 僅改變返回類型(無效)
int add(int, int) float add(int, int)
Java 方法簽名由方法名稱和其后的參數列表共同決定,僅改變返回類型編譯器無法重載。 不過方法重載(Method Overloading)允許改變返回類型和存取權限,但兩者不屬于方法簽名。
方法重載(Method Overloading)式多態性,即方法調用取決于調用時傳遞的參數(數量、類型、順序),屬于編譯時靜態多態性。
動態多態性:方法重寫(Method Overriding)方法重寫(Method Overriding)允許子類對父類可以訪問的方法,實現自定義行為,但是方法簽名需要保持一致。重寫的優點在于,無需修改父類代碼即可改變子類繼承的方法。
重寫形式:
重寫依賴繼承,通過父類引用,指向子類對象實現動態多態性。
public class Animal{ public void sound(){ System.out.println("Animal is making a sound"); } } public class Cat extends Animal{ @Override public void sound(){ System.out.println("Meow"); } public static void main(String args[]){ Animal obj = new Cat(); obj.sound(); } }
輸出:
Meow
重寫(覆蓋)規則:
方法簽名(方法名稱和參數列表)必須一樣,返回類型需要兼容。
不能降低方法的存取權限。
static, private, final 標記的方法以及類的構造方法不能被重寫(覆蓋)。
分析原因:
Java 通過方法簽名標識方法,因此重寫需要確保是子類繼承自父類的同一方法。
子類不可以降低父類方法的存取權限(可見性),但可以升級。繼承反映一種 “is a” 關系,子類是父類,支持父類所有對外開放的行為。降低方法的存取權限,使得父類作為統一接口方式調用方法的能力被破壞。
private, final 標記的方法以及父類的構造方法無法繼承,故無法重寫。
static 標記的方法為靜態方法屬于類,通過類名.方法名形式調用,無需依賴對象。
靜態方法和屬性會被子類繼承,子類同樣允許定義同名靜態方法和屬性,區別于實例方法“重寫”和屬性“重名”,這種情況被稱為“隱藏”。此時子類中調用同名的父類靜態方法和屬性,需要指明父類名.方法名或父類名.變量名。
多態性的類型可以分為運行時和編譯時,方法重寫(Method Overriding)代表運行時動態多態性,方法重載(Method Overloading)代表編譯時靜態多態性。
方法調用與方法體的關聯稱為綁定,有兩種類型的綁定:在編譯時發生的靜態綁定(Static Binding or Early Binding)和在運行時發生的動態綁定(Dynamic Binding or Late Binding)。
static, private, final 標記的方法以及類的構造方法是靜態綁定的,在編譯時確定所屬類的類型,因此這些方法無法覆蓋。其他非標記的方法可以稱為“虛函數”,Java 中其實并沒有“虛函數”的概念,所有普通函數(方法)默認都相當于 C++ 的”虛函數”允許覆蓋(Override),因此虛函數(Virtual Method)能夠根據運行時具體對象的類型進行動態綁定實現動態多態性,例如方法重寫(Method Overriding)。
靜態綁定示例:
class Human{ public static void walk() { System.out.println("Human walks"); } } class Boy extends Human{ public static void walk(){ System.out.println("Boy walks"); } public static void main( String args[]) { /* Reference is of Human type and object is * Boy type */ Human obj = new Boy(); /* Reference is of Human type and object is * of Human type. */ Human obj2 = new Human(); obj.walk(); obj2.walk(); } }
輸出:
Human walks Human walks
聲明為 static 的方法不能被重寫,但是能夠被再次聲明(隱藏)。
Static Binding vs Dynamic Binding
靜態綁定發生在編譯時,而動態綁定發生在運行時。
靜態綁定使用的是類信息:類的類型決定調用方法,而動態綁定使用的是對象信息:對象的類型決定調用方法。
方法重載使用靜態綁定,而方法重寫使用動態綁定。
綜合練習多態性示例程序:
class A { public String show(D obj) { // 方法一 return ("A and D"); } public String show(A obj) { // 方法二 return ("A and A"); } } class B extends A { public String show(B obj) { // 方法三 return ("B and B"); } public String show(A obj) { // 方法四 return ("B and A"); } } class C extends B { } class D extends B { } public class Main { public static void main(String[] args) { A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println("1--" + a1.show(b)); System.out.println("2--" + a1.show(c)); System.out.println("3--" + a1.show(d)); System.out.println("4--" + a2.show(b)); System.out.println("5--" + a2.show(c)); System.out.println("6--" + a2.show(d)); System.out.println("7--" + b.show(b)); System.out.println("8--" + b.show(c)); System.out.println("9--" + b.show(d)); } }
運行結果:
1--A and A 2--A and A 3--A and D 4--B and A 5--B and A 6--A and D 7--B and B 8--B and B 9--A and D
詳細分析:
A、B、C、D 各類繼承關系如圖所示:
A a1 = new A(); 正常創建對象 a1,涉及函數重載 show(),a1 具有調用方法一 show(D obj) 和方法二 show(A obj) 的能力。
a1.show(b) 由編譯器進行靜態綁定(前期綁定)方法二 show(A obj)。
a1.show(c) 由編譯器進行靜態綁定(前期綁定)方法二 show(A obj)。
a1.show(d) 由編譯器進行靜態綁定(前期綁定)方法一 show(D obj)。
A a2 = new B(); 多態創建父類引用,指向子類對象,a2 向上轉型具有調用 A 類方法一 show(D obj) 和方法二 show(A obj) 的能力,其中子類 B 重寫父類 A 的方法二 show(A obj) 為方法四 show(A obj)。記住向上轉型存在缺點,即不能調用子類中有,父類沒有的方法,如方法三 show(B obj)。
a2.show(b) 運行時動態綁定(后期綁定)方法四 show(A obj)。
a2.show(c) 運行時動態綁定(后期綁定)方法四 show(A obj)。
a2.show(d) 由編譯器進行靜態綁定(前期綁定)方法一 show(D obj)。
B b = new B(); 正常創建對象 b,涉及函數重載 show(),b 具有調用方法三 show(B obj) 和方法四 show(A obj) 的能力。同時 B 繼承自 A 因此擁有方法一 show(D obj) 和方法二 show(A obj) 其中方法二被方法四重寫覆蓋。
b.show(b) 由編譯器進行靜態綁定(前期綁定)方法三 show(B obj)。
b.show(c) 由編譯器進行靜態綁定(前期綁定)方法三 show(B obj)。
b.show(d) 由編譯器進行靜態綁定(前期綁定)方法一 show(D obj)。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71578.html
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:很多情況下,通常一個人類,即創建了一個具體的對象。對象就是數據,對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍圖或原型。在中,對象通過對類的實體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...
摘要:方法即為收集器,它接收高階函數和的后端掘金年的第一天,我坐在獨墅湖邊,寫下這篇文章。正因如此,所以最全系列教程后端掘金是從版本開始引入的一個新的,可以替代標準的。 設計模式之單例模式 - 掘金前言 作為一個好學習的程序開發者,應該會去學習優秀的開源框架,當然學習的過程中不免會去閱讀源碼,這也是一個優秀程序員的必備素養,在學習的過程中很多人會遇到的障礙,那就是設計模式。很多優秀的框架會運...
閱讀 1605·2021-11-04 16:11
閱讀 3316·2021-09-09 11:33
閱讀 1566·2019-08-30 15:54
閱讀 623·2019-08-30 15:44
閱讀 3180·2019-08-30 15:43
閱讀 2561·2019-08-30 13:06
閱讀 1701·2019-08-29 17:00
閱讀 903·2019-08-29 15:33