java单分派与多分派(多路分发和单路分发)
1. 分派的概念
变量被声明时的类型叫做变量的静态类型(Static Type) 又叫明显类型(Apparent Type)。变量所引用的对象的真实类型又叫做变量的实际类型(Actual Type)。
根据对象的类型而对方法进行的选择,就是分派(Dispatch)。根据分派发生的时期,可以将分派分为两种,即分派分静态分派和动态分派。
静态分派(Static Dispatch) 发生在编译时期,分派根据静态类型信息发生。方法重载(Overload)就是静态分派。(所谓的:编译时多态)
动态分派(Dynamic Dispatch) 发生在运行时期,动态分派动态地置换掉某个方法。面向对象的语言利用动态分派来实现方法置换产生的多态性。(所谓的:运行时多态)
方法重载(静态分派)Java通过方法重载来支持静态分派。下面考察下墨子骑马的故事。
public enum Outcome { WIN, LOSE, DRAW } ///:~interface Item {Outcome compete(Item it);Outcome eval(Paper p);Outcome eval(Scissors s);Outcome eval(Rock r);}class Paper implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return DRAW;}public Outcome eval(Scissors s) {return WIN;}public Outcome eval(Rock r) {return LOSE;}public String toString() {return "Paper";}}class Scissors implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return LOSE;}public Outcome eval(Scissors s) {return DRAW;}public Outcome eval(Rock r) {return WIN;}public String toString() {return "Scissors";}}class Rock implements Item {public Outcome compete(Item it) {return it.eval(this);}public Outcome eval(Paper p) {return WIN;}public Outcome eval(Scissors s) {return LOSE;}public Outcome eval(Rock r) {return DRAW;}public String toString() {return "Rock";}}public class RoShamBo1 {static final int SIZE = 20;private static Random rand = new Random(47);public static Item newItem() {switch (rand.nextInt(3)) {default:case 0:return new Scissors();case 1:return new Paper();case 2:return new Rock();}}public static void match(Item a, Item b) {System.out.println(a + " vs. " + b + ": " + a.compete(b));}public static void main(String[] args) {for (int i = 0; i < SIZE; i++)match(newItem(), newItem());}}RoshamBol.match()有2个item参数,通关过Item.compete()方法开始2路分发,要判定a的类型,分发机制会在a的实际类型的compete()内部起到分发作用。compete()方法通关过eval()来为另一个类型实现第二次分发, 将自身(this)作为参数调用eval(),能够调用重载过的eval()方法,这能够保留第一次分发的类型信息,第二次分发完成时,就能知道两个Item对象的具体类型了。这种实现也就是“访问者模式”的精华。 这种的详细解释请看: java实现多路分发整理至《java与模式》