Visitor pattern: overriding vs overloading
Asked Answered
C

2

6

For implementing a Visitor Pattern in Java you can use Overriding or Overloading. Does the choice depends or is it always preferable to choose one of the two? Because I don't see no disadvantages. Because I think the first and third example will always do the job?

Visitor with overriding

public interface Visitor {
   public void visitX(X x);
   public void visitY(Y y);
}
public class ConcreteVisitor {
   public void visitX(X x) { ... }
   public void visitY(Y y) { ... }
}

public abstract class XY {
   public abstract void accept(Visitor v);
}
public class X extends XY {
   // alternative: one implementation with reflection possible in super class
   public void accept(Visitor v) {
       v.visitX(this);
   }
}
public class Y extends XY {
   // alternative: one implementation with reflection possible in super class
   public void accept(Visitor v) {
       v.visitY(this);
   }
}

Visitor with overloading

public interface Visitor {
   public void visit(XY xy); // dummy (couldn't otherwise been used in XY class)
   public void visit(X x);
   public void visit(Y y);
}
public class ConcreteVisitor {
   public void visit(XY xy) { ... }
   public void visit(X x) { ... }
   public void visit(Y y) { ... }
}

public abstract class XY {
   public void accept(Visitor v) {
      v.visit(this); // Which is the compile-time/static type of this? XY?
   }
}
public class X extends XY {

}
public class Y extends XY {

}

Better Visitor with overloading

public interface Visitor {
   public void visit(X x);
   public void visit(Y y);
}
public class ConcreteVisitor {
   public void visit(X x) { ... }
   public void visit(Y y) { ... }
}

public abstract class XY {
   public abstract void accept(Visitor v);
}
public class X extends XY {
   public void accept(Visitor v) {
      v.visit(this);
   }
}
public class Y extends XY {
  public void accept(Visitor v) {
      v.visit(this);
  }
}
Centerpiece answered 22/12, 2013 at 14:57 Comment(3)
Also, there are no substantial differences between the 1st one and the 3rd one; there's an equivalent level of overriding going on in each. Your question is equivalent to "should I use overloads or methods with different names?".Isley
"should I use overloads or methods with different names?", it's indeed the same but I've to apply them to the Visitor Pattern and I've to consider the possible advantages and dissadvantages. But I see no difference or possible future problems at all. The burden of the work is always at the ConcreteVisitor; he'll have to implement the methods anyway.Centerpiece
Yup. Overloads are nothing more than syntax sugar. It requires the same amount of code either way.Isley
T
3

The Visitor pattern is in essence about covering an important use case of double dispatch in a single-dispatch language. It leverages the single-dispatch mechanism in a two-step idiom. Therefore if you use reflection for one of those two steps, you are no longer implementing Visitor.

The question of whether or not to use overloading is a minor point because it comes down to nothing more than the choice of name for all the visit methods. You can use either, but overloading makes more sense in professional code. While studying the pattern, separate names will make it easier to understand the Visitor pattern, which is a bit notorious for its convolutedness.

Tymon answered 22/12, 2013 at 15:18 Comment(5)
acceptVisitor(Visitor v) { Class cls = this.getClass(); Class[] param = new Class[1]; param[0] = cls; Method method = cls.getDeclaredMethod("visit" + cls.getName(), param); method.invoke(v,this); } Not really clean design I suppose, but it's in the course slides.Centerpiece
Yes, I know how to do it; my comment is that this is no longer the Visitor pattern and moreover, if you count in reflection, then you don't need the clunky Visitor in the first place.Tymon
I should also add that Visitors are often used to traverse very large data structures and the overhead of reflection may actually become an obstacle, as opposed to the straight Visitor design, which relies excusively on the fast method dispatch.Tymon
My experience has shown that the visitor pattern is hard to understand by newbies, and that overloading the visit() method makes it more difficult. I now use the non-overloaded version just for that reason.Britska
Good point, @JBNizet. Newbies will easily confuse the static character of overloading with the dynamic character of overriding, and miss the essential points which motivate each aspect of the Visitor. Actually, I remember myself falling for that!Tymon
M
1

This is true of any behavior, not just Visitor. You can choose either one, of course. Both work.

Sounds like a rehash of the "interface or abstract class?" question. You prefer abstract when there can be meaningful, non-abstract default behavior. Interfaces have no default, so every user is forced to implement the method. No assumptions are possible.

Medici answered 22/12, 2013 at 15:3 Comment(4)
The example was just for illustrating. I was more thinking about: are there possible problems possible with the static (compile-time) binding of methods (in the overload case) vs the dynamic (run-time) binding of object types (in the override case).Centerpiece
"problems"? What problems? You're imagining things.Medici
Ease of use, convenience, complexity, what if someone sees all the same implementations in the subclasses and decides to move it to an abstract superclass (example 2)? it doesn't work anymore because of the binding of the method at compile-time. With problems I didn't necessarily meant bugs, bad design, etc. It's for a course of software engeneering so there's the aspect 'human' that needs to be considered (because anyone can write code a machine can understand).Centerpiece
Unfortunately, none of the problems you correctly cite will be made better or worse by the choices you presented. Visitor is not an easy pattern to understand, like Factory or Facade. A lot of people will argue that the GoF Design Patterns are band-aids to correct deficiencies in the C++/Java/C# object-oriented programming model.Medici

© 2022 - 2024 — McMap. All rights reserved.