简体   繁体   中英

Interface inheritance hierarchy

As part of code refactoring, I have found some code duplicates that I'm trying to remove

I have an interface like one below, in an assembly I cannot modify.

public interface IArtifact
{
    void Accept(IArtifactVisitor visitor);
}

public  interface IArtifactVisitor
{
    void Visit(Topic topic);
}

In the references assembly, which I want to reuse existing interfaces there is the same function signature

public interface IArtifact
{
    void Accept(IArtifactVisitor visitor);
}

public  interface IArtifactVisitor
{
     void Visit(Topic topic);
     void Visit(NewTopic topic);
}

and the Accept looks something like this

public void Accept(IArtifactVisitor visitor)
{
    visitor.Visit(this);
}

In order to removed the code reuse, I have tried the following:

public interface MyIArtifact : IArtifact
{
    void Accept(MyIArtifactVisitor visitor);
}

public interface MyIArtifactVisitor : IArtifactVisitor
{
    void Visit(NewTopic topic);
}

but what this does is, it forces me in each implementation class to implement both Accept(MyIArtifactVisitor visitor) and Accept(IArtifactVisitor visitor)

Is there a better way to do this?

If I understand your question correctly, you only need to specify one method signature in your interface

public interface MyIArtifactVisitor : IArtifactVisitor
{
     void Visit(NewTopic topic);
}

And that's essentially it. So, if you want to impliment that, and the external interface, then you do something like the following

public class MyImplimentingClass : MyIArtifactVisitor, IArtifactVisitor 
{
     public void Visit(NewTopic topic)
     {}

     public void Visit(Topic topic)
     {}
}

The visitor pattern is screwed up, and IMHO it is non-sense to implement it through interfaces. The way you implement visitor pattern is as follows:

abstract class Artifact{
     internal abstract void Visit(ArtifactVisitor visitor);
}


class Topic : Artifact{
     internal override void Visit(ArtifactVisitor visitor)
     {
        visitor.Visit(this);
     }
}

class ArtifactVisitor{
    internal virtual void Visit(Artifact artifact)
    {
        artifact.Visit(this);
    }
    protected virtual void Visit(Topic topic)
    {
    }
}

class SomeSpecificTopicVisitor : ArtifactVisitor
{
     protected override void Visit(Topic topic)
     {
         //do something with topics
     }     
}

From this state, you can start inheriting your own visitors from ArtifactVisitor. You will only override the methods which you actually need.

The visitor pattern is not very extensible. It is only useful if the set of inheritors is fixed and will not change significantly. Nevertheless, if you use it properly, it will nicely solve your double dispatching problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM