可以看到,重载的分派是根据静态类型进行的。
java的方法重写是根据实际类型来的(动态分派),编译器编译时并不知道其真实类型,而是运行时动态决定的。
一个对象又叫做它所包含的方法的接收者,java中的动态分派,要调用哪一个方法,是由这个对象的真实类型决定的。
如果能够根据参数和接收者来动态的决定调用某个方法,这就是动态的多分派语言,如果可以根据这两种方式来动态的决定方法调用,就是动态双重分派,但前面已经说了,java中重载是根据静态类型进行的,所以java只能动态的根据接收者来进行方法调用,即java是动态单分派语言,如果要实现双重分派,就必须通过设计模式来完成。
OK,讲到重点了,访问者模式正是实现双重分派的模式。java中通过两次方法调用来实现两次分派。
既然重载不能完成动态分派,我们就添加一个Visitor:
public class MultiDispatch { public static void main(String args[]){ Child child = new Child(); child.print(); child.print(new Vistor()); }}class Father{ void print(){ System.out.println("父类"); }}class Child extends Father{ void print(){ System.out.print("子类"); } void print(Vistor c){ c.print(this); }}class Vistor { public void print(Child child){ child.print(); }}//输出:子类子类
这样,动态双重分派也算是完成了(通过调用一个其它对象的方法,传入自己,在其他类的这个方法中再通过传入的这个参数调用自己。如果还是不清楚,请继续看下面的例子)。那么这个有什么用呢?下面继续解释。
比如我们有个app需要接收用户的反馈,用户由会员和普通用户,因为反馈太多,并不是所有反馈都会被记录到有效反馈表中,是否记录为有效通常不是用户说了算,而是有我们自己定。
本例中的用户就是抽象元素:
//抽象元素public intece User { void accept(Visitor visitor);}
具体的用户就是具体元素,本例有两个:
//普通用户,具体元素public class UserOrdinary implements User{ String estimation; public UserOrdinary(String estimation){ this.estimation = estimation; } @Override public void accept(Visitor visitor) { visitor.visit(this);//这个就是重点,第一次分派是调用accept()方法时根据接收者的实际类型来调用的,第二次分派就是通过visitor.visit(this),传入静态类型,然后再visit()方法中反过来调用this本身的方法。 } String getEstimation(){ return estimation; }}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-33893-32.html
高温消毒
至少还要几十年时间吧
伊拉克肯定向中俄暗盟倾斜的