ozgur
ozgur

Reputation: 2719

How to implement Interface method with subclass argument?

This is the interface

public interface ITransporter
{
    TransporterType TransporterType { get; set; }
    TransportActionResults BeginTransport(
        Project sourceProject, 
        ProjectBase targetProject);

    bool CheckTargetExists(ProjectBase project);
}

Here ProjectBase is an abstract class for all types of project classes. Here is the method inside the class that implements ITransporter interface.

public class LocalTransporter : ITransporter
{
    public TransportActionResults BeginTransport(
        Project sourceProject, 
        TargetLocalProject targetProject)
    {
        return TransportActionResults.Success;
    }

This TargetLocalProject class inherits from ProjectBase class. However, I get an error that says "LocalTransporter class does not implement interface member" and points to the BeginTransport method.

Here is my problem. I need to implement the interface's BeginTransport method using base class ProjectBase because there are couple of different project classes inherited from the base class and we don't know which one will be used.

Moreover, there are couple of differen Transporter types so that I need to interact with it using an interface ITransporter.

Note: I considered implementing the method using ProjectBase instead of TargetLocalProject but when using LocalTransporter directly (instead of thruogh interface) the argument's type should be the specific Project type instead of base class.

I hope I made myself clear. So, is there a way to implement this interface method using base class in interface but subclass in implemented method?

Upvotes: 0

Views: 2576

Answers (2)

lsedlacek
lsedlacek

Reputation: 323

You could provide an explicit interface implementation as follows:

internal class LocalTransporter : ITransporter
{
    public TransportActionResults BeginTransport(
        Project sourceProject,
        TargetLocalProject targetProject)
    {
        // specific implementation
        return TransportActionResults.Success;
    }

    public TransporterType TransporterType { get; set; }

    TransportActionResults ITransporter.BeginTransport(Project sourceProject, ProjectBase targetProject)
    {
        // generic implementation
        return TransportActionResults.Success;
    }

    public bool CheckTargetExists(ProjectBase project)
    {
        return true;
    }
}

You may want to consider using the visitor pattern here.

Upvotes: 1

Ron Beyer
Ron Beyer

Reputation: 11273

You can use generics for this, just change your interface a little bit:

public interface ITransporter<T> where T : ProjectBase
{
    TransporterType TransporterType { get; set; }
    TransportActionResults BeginTransport(Project sourceProject, T targetProject);

    bool CheckTargetExists(T project);
}

Then you can implement it in your concrete class:

public class LocalTransporter : ITransporter<TargetLocalProject>
{
    public TransportActionResults BeginTransport(Project sourceProject, TargetLocalProject targetProject)
    {
        return TransportActionResults.Success;
    }
}

Upvotes: 8

Related Questions