使用继承接口时遇到问题。我将在下面的例子中解释我的问题。假设我有接口IFlyable
:
public interface IFlyable
{
IVerticalSpeed Speed { get; set; }
}
它包含IVerticalSpeed
接口。我创建了另一个名为ISpeed
的接口,它继承自IVerticalSpeed
接口:
public interface ISpeed : IVerticalSpeed
{
int MaxSpeed { get; set; }
}
在下一步中,我创建了一个实现Fly
接口的类IFlyable
:
public class Fly : IFlyable
{
public IVerticalSpeed Speed { get; set; }
}
一切都很好......但如果我想将IVerticalSpeed
接口替换为继承自ISpeed
接口的IVerticalSpeed
接口,该怎么办?
public class Fly : IFlyable
{
public ISpeed Speed { get; set; }
}
我认为一切都应该没问题,因为我的ISpeed
接口是IVertialSpeed
接口+ ISpeed
接口contatins的任何东西。但那是不对的。我得到的错误是:“Fly没有实现接口成员IFlyable.Speed(...)。为什么?
答案 0 :(得分:2)
所有答案都显示了可能的解决方案,但实际上没有人回答这个重要问题:
我认为一切都应该没问题,因为我的
ISpeed
接口是IVertialSpeed
接口+ISpeed
接口contatins的任何东西。但那是不对的。我得到的错误是:" Fly没有实现接口成员IFlyable.Speed
(...)。的为什么吗
你自己说过了。 ISpeed
是IVerticalSpeed
,但并非所有IVerticalSpeed
都是ISpeed
,因此您根本不满足合同。
如果您的代码被允许并且我想执行以下操作会发生什么:
public interface IMyOtherSpeed: IVerticalSpeed { ... }
IFlyable myFly = new Fly();
IMyOtherSpeed mySpeed = new MyOtherSpeed();
myFly.Speed = mySpeed; //Runtime error, mySpeed is not an ISpeed?!?
你现在看到了这个问题?您违反了界面合同,因为当您的班级接受任何 ISpeed
时,您的班级才会接受IVerticalSpeed
。
答案 1 :(得分:1)
如果您使用泛型,您可以执行类似
的操作public interface IFlyable<out T> : where T IVerticalSpeed
{ T Speed {get;set;} }
然后在你的课堂上你会做类似
的事情public class Fly : IFlyable<SomeSpeedClass>
{
public SomeSpeedClass Speed{get;set}
}
答案 2 :(得分:1)
因为您的媒体签名必须保持100%相同。您可以实施新属性,作为解决方法。但它也有其局限性。
如果您的继承可以双向工作,可以执行此操作。您已经知道,所有ISpeed
都是IVerticalSpeed
。但事实并非如此。并非所有IVerticalSpeed
都是ISpeed
。因此,我们可以为您的课程提供另一种方法,但在这一点上它将面临一个问题:
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;
}
}
}
这不是代码问题,这是一个设计问题。如果有人为您IVerticalSpeed
设置Fly
,您想做什么?因为您的界面说明了这一点。也许你不想要制定者?
答案 3 :(得分:0)
而不是
public class Fly : IFlyable
{
public ISpeed Speed { get; set; }
}
您应该匹配IFlyable
界面
public class Fly : IFlyable
{
public IVerticalSpeed Speed { get; set; }
}
接口不是继承,必须完全匹配。
编辑:让我重新说一下,实现其他接口的接口不是继承,因此错误。接口必须与我完全匹配,这就是它引发错误的原因(ISpeed!= IVerticalSpeed)
答案 4 :(得分:0)
您还没有显示IVerticalSpeed
,但如果您能控制它,请考虑
public interface IFlyable<out TSpeed>
where TSpeed : IVerticalSpeed
{
TSpeed Speed { get; set; }
}
然后在Fly
这样实现
public class Fly : IFlyable<ISpeed>
{
public ISpeed Speed { get; set; }
}