Seite 1 von 1

Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 11:59
von m.hosseinian
"Can we move the implementation of accept higher up the Element hierarchy?"
According to the answer on the slides: "No. The method that is called by `v.visit(this)` is determined at compile-time."
But, I'm not so clear with this answer. Can anyone lighten me a little bit up with this, possibly with an example?
Thank you,
BR, Moe

Re: Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 13:01
von ayushmaan_jain

Code: Alles auswählen


public  abstract class Pizza
{
    public abstract void print();
    public void accept(Visitor v)
    {
        v.accept(this);
    }
    
}

class CheesePizza extends Pizza{

    @Override
    public void print()
    {
        // TODO Auto-generated method stub
        System.out.println("Cheesse Pizza");
        
    }
    
    
}
class VegPizza extends Pizza{
   
   public void doSomething(){ /*Did something */ }


    @Override
    public void print()
    {
        // TODO Auto-generated method stub
        System.out.println("Veg Pizza");
        
    }
    
}
interface Visitor {
    public void accept(Pizza p);
}

class PizzaTypeVistor implements Visitor{

    @Override
    public void accept(Pizza aP)
    {
        // TODO Auto-generated method stub
        aP.print();
        
    }
    
}
If you see this code, I can call only those methods which are defined in abstract class. Now lets say you want to call doSomething method in Concrete Visitor i.e PizzaTypeVistor, you can't do that. But if accept method would have been in Concrete classes, it would not be a problem to call doSomething method

It's what I have understood so far. Please let me know your views as well on this.


SJ

Re: Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 19:03
von ayushmaan_jain
In short, Some mainstream languages(e.g.) don't support double dispatch, thats why function is not up there in hierarchy.

Re: Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 19:40
von m.hosseinian
actually I didn't see your design as Visitor's applicant. Then I changed it this way:

Code: Alles auswählen

public abstract class Pizza {
	public abstract void print();
	public void accept(Visitor v) {
		v.visit(this);  //<=
	}
}

class CheesePizza extends Pizza {

	@Override
	public void print() {
		PizzaPrintVistor pv = new PizzaPrintVistor();
		accept(pv);

	}
}

class VegPizza extends Pizza {

	public void doSomething() { /* Did something */
	}

	@Override
	public void print() {
		PizzaPrintVistor pv = new PizzaPrintVistor();
		accept(pv);
	}
}

interface Visitor {
	public void visit(CheesePizza p);

	public void visit(VegPizza p);
}

class PizzaPrintVistor implements Visitor {

	@Override
	public void visit(CheesePizza aP) {
		System.out.println("Cheesse Pizza");
	}

	@Override
	public void visit(VegPizza aP) {
		System.out.println("Veg Pizza");
	}
}

class test {
	public static  void main(String[] args) {
		new CheesePizza().print();
		new VegPizza().print();
	}

}
The main point in this pattern, as I see it, is that concrete visitor(s) should have different visit methods for each element types that implement the feature in question specifically for that type.
In the type elements themselves the required feature should be realized by forwarding the request to corresponding visitor concrete class. By the way, this design is not optimum but it shows the point

Now I'm getting this compilation error: "The method visit(CheesePizza) in the type Visitor is not applicable for the arguments (Pizza)" at the line I marked with "<=".

I guess it's cleared up the things for me.
However thanks for your contribution.

Re: Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 19:50
von ayushmaan_jain
Thanks for refining the code :)

Re: Reflections on the Visitor Structure

Verfasst: 9. Jul 2015 19:58
von m.hosseinian
you're welcome, actually the problem is related to type checking on compile time, because visit is not declared for abstract that otherwise in order to implement the feature for each element type you have to explicitly type check/type cast the argument which does not follow OCP principle.
And you're right, not supporting double/multiple dispatch could be relevant here. But, I have to say I cannot be sure how; I have to stretch my mind beyond the type-check of Java and other PLs I have dealt with, that's so hard for me at this point :)