Reputation: 877
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?
Upvotes: 4
Views: 2156
Reputation: 3541
Instead of
public class Fly : IFlyable
{
public ISpeed Speed { get; set; }
}
You should match the IFlyable
interface
public class Fly : IFlyable
{
public IVerticalSpeed Speed { get; set; }
}
Interfaces are not inheritance, must be matched exactly.
Edit: Let me rephrase, interfaces that implementing other interfaces is not inheritance, hence the error. Interfaces must me matched exactly, that's is why it raises the error (ISpeed != IVerticalSpeed)
Upvotes: 1
Reputation: 32780
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 isIVertialSpeed
interface + anything thatISpeed
interface contatins. But that is not right. I get error which says: "Fly does not implement interface memberIFlyable.Speed
(...). Why?
You've said it yourself. ISpeed
is an IVerticalSpeed
, but not all IVerticalSpeed
s are ISpeed
s 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
.
Upvotes: 4
Reputation: 77364
Because your property's signature must stay 100% the same. You can implement a new property, as a workaround. But it has it's limitations, too.
You can do this if your inheritance would work both ways. You already know, all ISpeed
s are IVerticalSpeed
s. But that's not the case the other way round. Not all IVerticalSpeed
s are ISpeed
s. So we can give your class another method, but it will face a problem at exactly that point:
public interface IVerticalSpeed
{
int Value { get; set; }
}
public interface IFlyable
{
IVerticalSpeed Speed { get; set; }
}
public interface ISpeed : IVerticalSpeed
{
int MaxSpeed { get; set; }
}
public class Fly : IFlyable
{
public ISpeed Speed { get; set; }
IVerticalSpeed IFlyable.Speed
{
get
{
return this.Speed;
}
set
{
// Wow, wait, you want to SET an IVerticalSpeed,
// but not every IVerticalSpeed is an ISpeed... what now?
// this.Speed = value;
}
}
}
This is not a problem of code, this is a design problem. What do you want to do, if someone sets an IVerticalSpeed
to your Fly
? Because your interface says that's allowed. Maybe you don't want setters?
Upvotes: 1
Reputation: 5480
You haven't shown IVerticalSpeed
, but if you have control of it consider
public interface IFlyable<out TSpeed>
where TSpeed : IVerticalSpeed
{
TSpeed Speed { get; set; }
}
then implemented in Fly
like this
public class Fly : IFlyable<ISpeed>
{
public ISpeed Speed { get; set; }
}
Upvotes: 0
Reputation: 4219
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}
}
Upvotes: 2