Search code examples
c#design-patternsvisitor-pattern

Visitor Pattern "does not implement interface" error


It's first time that I try to implement the visitor pattern (using c#), I'm sorry if I did something wrong! However, I implemented this visitor pattern:

public interface VisitableElement
{
    void accept (VisitorElement visitor); 
}

public interface VisitorElement
{
    void visit (VisitableElement visitable);
}

public class SomeClass : VisitableElement
{
    ...
    public void accept(VisitorElement visitor)
    {
        ...
    }
}
//here there are other classes which implement VisitableElement (not useful for the example)

class Visitor: VisitorElement
{
...
    public void visit (SomeClass someobject)
    {
        ...
    }
//othes implementation of visit (one for each element of class of the hierarcy)
...
}

But when I try to compile this error is returned:

Error   1   'Visitor' does not implement interface member 'NameSpace.VisitorElement.visit(NameSpace.VisitableElement)'

...But why? I implemented it through visit(SomeClass someobject)!

The funny thing is that if I try to add:

    public void visit(VisitableElement visitable)
    {
        this.visit(visitable);
    }

Then everything works fine, but it should be unecessary to implement it in this way (and the first visit method should be enough!)


Solution

  • The interface VisitorElement requires that your class implements the method void visit (VisitableElement visitable).

    The visit method you implemented does not fulfill this requirement, since it only allows arguments of type SomeClass.

    While each SomeClass is a VisitableElement, the interface requires that the method accepts any type that implements VisitableElement, not only SomeClass.


    If you want your visit method to only accept arguments of type SomeClass, consider using a generic VisitorElement<T> and an explicit interface implementation:

    public interface VisitableElement
    {
        void accept (VisitorElement visitor); 
    }
    
    public class SomeClass : VisitableElement
    {
        public void accept(VisitorElement visitor) { }
    }
    
    public interface VisitorElement
    {
        void visit (VisitableElement visitable);
    }
    
    public interface VisitorElement<T> : VisitorElement where T : VisitableElement
    {
        void visit (T visitable);
    }
    
    class Visitor: VisitorElement<SomeClass>
    {
        public void visit (SomeClass someobject) { }
    
        void VisitorElement.visit(VisitableElement visitable) { }
    }
    

    This way, you can only call the visit (SomeClass someobject) overload as long as you don't cast your Visitor instance to the non-generic VisitorElement. In the non-generic visit method, you could try to cast visitable to SomeClass and call the generic version as fallback (or do whatever you like).


    As it is not entirely clear to me what you want to achieve, it's hard to say what is the best thing to do in your case.