访问者模式用到了一种双分派的技术——静态分派和动态分派
擴展
訪問者模式用到了一種雙分派的技術。
1,分派:
變量被聲明時的類型叫做變量的靜態類型,有些人又把靜態類型叫做明顯類型;
而變量所引用的對象的真實類型又叫做變量的實際類型。
比如?Map map = new HashMap()?,map變量的靜態類型是?Map?,實際類型是?HashMap?。
?
根據對象的類型而對方法進行的選擇,就是分派(Dispatch),分派(Dispatch)又分為兩種,
即靜態分派和動態分派。
靜態分派(Static Dispatch)?發生在編譯時期,分派根據靜態類型信息發生。靜態分派對于我們來說并不陌生,方法重載就是靜態分派。
動態分派(Dynamic Dispatch)?發生在運行時期,動態分派動態地置換掉某個方法。Java通過方法的重寫支持動態分派。
2,動態分派:
通過方法的重寫支持動態分派
public class Animal {public void execute() {System.out.println("Animal");} } ? public class Dog extends Animal {@Overridepublic void execute() {System.out.println("dog");} } ? public class Cat extends Animal {@Overridepublic void execute() {System.out.println("cat");} } ? public class Client {public static void main(String[] args) {Animal a = new Dog();a.execute();Animal a1 = new Cat();a1.execute();} }上面代碼的結果大家應該直接可以說出來,這不就是多態嗎!
運行執行的是子類中的方法。
Java編譯器在編譯時期并不總是知道哪些代碼會被執行,因為編譯器僅僅知道對象的靜態類型,而不知道對象的真實類型;
而方法的調用則是根據對象的真實類型,而不是靜態類型。
靜態分派:
通過方法重載支持靜態分派
public class Animal { } ? public class Dog extends Animal { } ? public class Cat extends Animal { } ? public class Execute {public void execute(Animal a) {System.out.println("Animal");} ?public void execute(Dog d) {System.out.println("dog");} ?public void execute(Cat c) {System.out.println("cat");} } ? public class Client {public static void main(String[] args) {Animal a = new Animal();Animal a1 = new Dog();Animal a2 = new Cat(); ?Execute exe = new Execute();exe.execute(a);exe.execute(a1);exe.execute(a2);} }這個結果可能出乎一些人的意料了,為什么呢?
重載方法的分派是根據靜態類型進行的,這個分派過程在編譯時期就完成了。
4,雙分派:
所謂雙分派技術就是在選擇一個方法的時候,不僅僅要根據消息接收者(receiver)的運行時區別,還要根據參數的運行時區別。
public class Animal {public void accept(Execute exe) {exe.execute(this);} } ? public class Dog extends Animal {public void accept(Execute exe) {exe.execute(this);} } ? public class Cat extends Animal {public void accept(Execute exe) {exe.execute(this);} } ? public class Execute {public void execute(Animal a) {System.out.println("animal");} ?public void execute(Dog d) {System.out.println("dog");} ?public void execute(Cat c) {System.out.println("cat");} } ? public class Client {public static void main(String[] args) {Animal a = new Animal();Animal d = new Dog();Animal c = new Cat(); ?Execute exe = new Execute();a.accept(exe);d.accept(exe);c.accept(exe);} }在上面代碼中,客戶端將Execute對象做為參數傳遞給Animal類型的變量調用的方法,這里完成第一次分派,這里是方法重寫,所以是動態分派,也就是執行實際類型中的方法,
同時也將自己this作為參數傳遞進去,這里就完成了第二次分派,這里的Execute類中有多個重載的方法,而傳遞進行的是this,就是具體的實際類型的對象。
說到這里,我們已經明白雙分派是怎么回事了,但是它有什么效果呢?就是可以實現方法的動態綁定,我們可以對上面的程序進行修改。
運行結果如下:
雙分派實現動態綁定的本質,就是在重載方法委派的前面加上了繼承體系中覆蓋的環節,由于覆蓋是動態的,所以重載就是動態的了。
?
總結
以上是生活随笔為你收集整理的访问者模式用到了一种双分派的技术——静态分派和动态分派的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JDK源码解析 迭代器模式在JAVA的很
- 下一篇: spring使用回顾