Sys
Sys

Reputation: 413

Derived Interface with derived interface member

I have 2 base interfaces, IViewBase (which all views will implement) and IPresenterBase (which all presenters will implement):

public interface IViewBase { }

public interface IPresenterBase
{
    IViewBase View { get; set; }
}

Then i've created a new interface ILogPresenter that derives from IPresenterBase and ILogView deriving from IViewBase:

public interface ILogPresenter : IPresenterBase { }

public interface ILogView : IViewBase{ }

When i create a class that implements ILogPresenter,

public class LogPresenter: ILogPresenter
{
    public ILogView View { get; set; }
}

I get an error:

'LogPresenter' does not implement interface member 'IPresenterBase.View'. 'LogPresenter.View' cannot implement 'IPresenterBase.View' because it does not have the matching return type of 'Views.IViewBase'.

I cannot set the return type of LogPresenter.View to ILogView which derives from IViewBase? I would like implement ILogPresenter with a different IView which derives from IViewBase.

Upvotes: 6

Views: 6148

Answers (2)

bruno conde
bruno conde

Reputation: 48265

You can do this with generics:

public interface IViewBase { }

public interface IPresenterBase<T> where T : IViewBase
{
    T View { get; set; }
}

public interface ILogPresenter : IPresenterBase<ILogView> { }

public interface ILogView : IViewBase { }

public class LogPresenter : ILogPresenter
{
    public ILogView View { get; set; }
}

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1500385

You probably want to use generics here:

public interface IViewBase { }

public interface IPresenterBase<T> where T : IViewBase
{
    T View { get; set; }
}

then:

public interface ILogPresenter : IPresenterBase<ILogView> { }

public interface ILogView : IViewBase{ }

Aside from covariant return types not being supported in C# (which would cause a problem even just with a getter) you have a fundamental problem in the original. I could do:

IPresenterBase foo = new LogPresenterImpl();
foo.View = new SomeOtherView();

where SomeOtherView implemented IVewBase but not ILogView. How would you expect your property to cope with that?

The generic version above solves this by allowing a presenter to express what kind of view it's presenting.

Upvotes: 9

Related Questions