For the first time I implement, and something did not work.

public interface FieldVisitor { Object visit(Field field); } 

And these are methods from implementation:

 private FieldVisitor factory = new FieldVisitor() { public Object visit(PresetField presetField) { .... } public Object visit(StringField stringField) { .... } @Override public Object visit(Field field) { System.out.println(field.getClass()); .... } }; 

I call this:

 public Node getFieldFor(Field field) { return (Node) factory.visit(field); } 

It can be seen that objects of different classes are coming:

 class com.dma.params.model.field.PresetField class com.dma.params.model.field.PresetField class com.dma.params.model.field.NumberField class com.dma.params.model.field.NumberField class com.dma.params.model.field.StringField class com.dma.params.model.field.BooleanField 

However, as I see, I only get to the method for the superclass. In general, as I understand what type of pointer, such a function is called. How can I change this behavior? That function for actual type was caused or I somewhere tupanul with a pattern?

  • one
    I will not say the pattern, but by the code I see, you call the visit(Field field) method, this means that polymorphism will be only for the parameter of the Field type, and the visit(PresetField), visit(StringField) are completely independent, the overload is not override - markov
  • You have an overloaded method visit (...), you call its factory.visit(field) , where field is an object of the Field class, respectively, and the visit(Field field) method is called. And I don’t see a superclass at all. - post_zeew
  • I tried to specify in the interface overloaded versions for all types of input parameters (that is, not only to overload but also to override each option - the effect is zero. And it does not play a role in this case, because I call this method right away with the specific implementation, and not with the interface. - Uraty
  • Forgot to specify, Field is a superclass for everyone) - Uraty
  • one
    no matter whether it is a superclass or not, it is important that the method is called for the Field type, it is for this type that it is called, it doesn’t matter which subclass you transfer there - the method is called for the Field - markov

1 answer 1

Because everything is completely wrong.

First, the visitor interface must declare methods for all classes in the hierarchy.

 public interface FieldVisitor { Object visit(PresetField field); Object visit(StringField field); ... } 

Second, the ancestor of the hierarchy declares an abstract accept method in which the visitor is accepted

 class Field { ... public abstract void accept(FieldVisitor visitor); ... } 

Third, specific such descendants implement / redefine the acceptor method in such a way that the visitor method is called for the desired (own) class

 class StringField { ... @Override public abstract void accept(FieldVisitor visitor) { visitor.visit(this); // вызов visit(StringField field) } ... } 

Finally, a visitor can visit the hierarchy by first implementing the visitor's interface by calling an acceptor.

 ... field.accept(new FieldVisitor() { @Override Object visit(PresetField field) { ... } @Override Object visit(StringField field) { ... } }); ... 

Thanks to polymorphism, the accept of a particular class is called, which in turn calls its own overloaded visitor method.

  • Yeah, I think I’m trying to do it now, thanks a lot) - Uraty
  • Great, now this pattern has finally reached me) Thank you) - Uraty