Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface inheritance. Does not implement interface error

I have a problem with using inherited interface. I will explain my problem on example below. Let's say I have Interface IFlyable:

public interface IFlyable
{
    IVerticalSpeed Speed { get; set; }
}

It contains IVerticalSpeed interface. I created another interface called ISpeed which inherits from IVerticalSpeed interface:

public interface ISpeed : IVerticalSpeed
{
    int MaxSpeed { get; set; }
}

In next step I created a class Fly which implement IFlyable interface:

public class Fly : IFlyable
{
    public IVerticalSpeed Speed { get; set; }
}

Everything is fine... but what if I wanted to replace IVerticalSpeed interface to ISpeed interface which inherits from IVerticalSpeed interface?

public class Fly : IFlyable
{
    public ISpeed Speed { get; set; }
}

I thought that everything should be fine because my ISpeed interface is IVertialSpeed interface + anything that ISpeed interface contatins. But that is not right. I get error which says: "Fly does not implement interface member IFlyable.Speed (...). Why?

like image 239
Adam Stepniak Avatar asked Mar 09 '23 18:03

Adam Stepniak


2 Answers

All answers show you possible solutions but none actually answer the important question here:

I thought that everything should be fine because my ISpeed interface is IVertialSpeed interface + anything that ISpeed interface contatins. But that is not right. I get error which says: "Fly does not implement interface member IFlyable.Speed (...). Why?

You've said it yourself. ISpeed is an IVerticalSpeed, but not all IVerticalSpeeds are ISpeeds so you are not satisfying the contract at all.

What would happen if your code was allowed and I wanted to do the following:

public interface IMyOtherSpeed: IVerticalSpeed { ... }
IFlyable myFly = new Fly();
IMyOtherSpeed mySpeed = new MyOtherSpeed();

myFly.Speed = mySpeed; //Runtime error, mySpeed is not an ISpeed?!?

You see the issue now? You'd be breaking the interface's contract, becuase your class only accepts ISpeed when it should accept any IVerticalSpeed.

like image 199
InBetween Avatar answered Mar 19 '23 06:03

InBetween


If you use generics you can do something like

public interface IFlyable<out T> : where T IVerticalSpeed
{ T Speed {get;set;} }

Then in your class you would do something like

public class Fly : IFlyable<SomeSpeedClass>
{
  public SomeSpeedClass Speed{get;set}
}
like image 32
dcg Avatar answered Mar 19 '23 08:03

dcg