Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 469
Sys Avatar asked Nov 04 '09 10:11

Sys


2 Answers

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.

like image 123
Jon Skeet Avatar answered Sep 28 '22 18:09

Jon Skeet


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; }
}
like image 26
bruno conde Avatar answered Sep 28 '22 17:09

bruno conde