導語 多態也叫動態綁定 後期綁定 運行時綁定
- 輸入錯誤的數字,如何得到正確的結果呢 方法調用tune(Instruments i) tune(wind)
- 多態通過分離做什麼和怎麼做,從另一個角度講接口和實現分離開來。接口就是公開調用的方法,而實現就是具體的方法,
父類(或抽象類,或inteface接口)來聲明做什麼,子類來實現怎麼做。 - 封裝 通過合併特徵和行爲來創建新的數據類型。實現隱藏則通過將細節“私有化”把接口和實現分離開來。
- 多態方法允許一種類型表現出與其他相似類型之間的區別,只要他們都是從同一基類導出的子類。
- 繼承允許對象視爲它自己本身的類型或者基類型來處理。
- 多態的好處:多態不帶能夠改善代碼的組織結構和可讀性,還能夠創建可擴展的程序。(這些都需要大量編程才能理解的)
- 多態的作用是消除類型之間的耦合關係,即一個類型不依賴於另一個類型。
1.什麼叫多態(動態綁定、後期綁定和運行時綁定)
- 講一個方法調用同一個方法主體關聯起來被稱作綁定。綁定機制是由java語言所定的,不必深究他爲什麼會在前期綁定......。
List list = new ArrayList(); list.remove(0);
如上述代碼,list.remove(0),這個方法調用將與ArrayList類裏面的remove()方法主體關聯,並執行主體裏面的代碼,這就叫做綁定。這個是後期綁定。、 - 前期綁定:方法調用在程序執行前進行綁定。(由編譯器和連接程序實現)就是說方法調用明確與那個方法主體關聯。只有明確只有這個類有這個方法的情況。不必深究爲什麼,這是java的機制,java自己可以知道怎樣關聯。
- 動態綁定:也就是多態,在運行時根據對象的類型進行綁定,也就是說程序在運行過程中進行方法的調用是可以知道其對象類型的。【子類繼承同一個父類,調用父類的可被複用方法,不知道調用哪一個,
因爲向上轉型可能會new一個子類,如上面的list】
也就是說在程序運行過程中的方法調用後java自己會根據對象類型進行判斷與那個方法主體關聯並執行其中的代碼。這是多麼的神奇,不過不必深究。 - 如果一種語言想實現多態,就必須有某種機制,以便在運行時能判斷對象的類型。就像java的多態機制一樣。
- java中除了static和final方法(private 屬於final方法)之外,其他所有方法都是後期綁定的。
有人可能會問 public等修飾的方法,別的類中可以有相同名字的public方法
2.通過代碼說明什麼是多態【產生正確的行爲】,而什麼有是前期綁定
package com.yue.dt; import java.util.Random; //父類 class Shape { //公開的接口 public void draw(){} public void erase(){} } //子類 class Circle extends Shape{ public void draw() { System.out.println("Circle.draw()!"); } public void erase() { System.out.println("Circle.erase()!"); } } class Square extends Shape{ public void draw() { System.out.println("Square.draw()!"); } public void erase() { System.out.println("Square.erase()!"); } } class Triangle extends Shape{ public void draw() { System.out.println("Triangle.draw()!"); } public void erase() { System.out.println("Triangle.erase()!"); } } class RandomShapeGenerator { private Random rand = new Random(47); public Shape next() { switch (rand.nextInt(3)) { default: case 0: return new Circle(); case 1: return new Square(); case 2: return new Triangle(); } } } public class Shapes { private static RandomShapeGenerator gen = new RandomShapeGenerator(); public static void main(String[] args) { Shape[] s = new Shape[9]; for (int i = 0; i < s.length; i++) { s[i] = gen.next(); } for (Shape shp : s) { shp.draw(); } } }
- 上面的代碼,在Shapes的main方法中,我們使用gen.next()獲取一個Shape子類並賦予Shape引用,Shape引用是父類,
那麼問題來了爲什麼不執行父類中的draw(),這是因爲java的機制,優先執行子類中重寫的父類中的方法,子類那麼多,怎麼知道
執行的是哪一個子類的方法主體呢,這就是java的多態機制了,在運行時根據對象的類型將方法調用與相應的方法主體關聯起來,
並執行其中的代碼。 - 如果是個private 或final 或static 就是前期綁定啦,也就是說在程序執行前就將方法調用與方法體關聯起來啦。
3.什麼時候會產生多態,動態綁定、運行時綁定
- 如果2的解釋還不明白的話,那下面的解釋就很通透啦
- 方法調用不知道是調用哪個類中的方法主體時[代碼],多態就會出現,也就是說可能會伴隨着繼承的情況,也有可能這個方法是public protect等權限修飾的。
- 一個名稱的方法被多個類所擁有且不是static private final的時候,多態將會出現,因爲在程序運行期間方法調用的時候,方法調用與那個類中的方法主體(方法代碼)關聯並執行需要多態進行判斷。
當你 Shape s = new Circle();並執行s.draw(),你怎麼知道s.draw()這個方法調用會執行Circle中的draw方法主體還是Shape中的方法主體,還是Square中方法主體呢????
這一切都依賴於多態。也就是在程序運行期間方法調用時判斷對象的類型,並執行類中的方法主體。java會優先調用子類的覆蓋方法,這就是多態機制(很片面)。