【问题标题】:Interface inheritance. Does not implement interface error接口继承。不实现接口错误
【发布时间】:2023-03-13 19:25:01
【问题描述】:

我在使用继承接口时遇到问题。我将在下面的示例中解释我的问题。假设我有接口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 接口替换为继承自IVerticalSpeed 接口的ISpeed 接口怎么办?

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

我认为一切都应该没问题,因为我的ISpeed 接口是IVertialSpeed 接口+ISpeed 接口包含的任何东西。但这是不对的。我收到错误消息:“Fly 没有实现接口成员 IFlyable.Speed (...)。为什么?

【问题讨论】:

  • 你没有显示IVerticalSpeed
  • @Seabizkit - 不,但这不重要。 interface IVerticalSpeed {} 就够了。
  • 在亚当,不,更多信息会有所帮助。我看不出 IVerticalSpeed 是否具有 IVerticalSpeed 作为属性.... 奇怪的是,但问题也是如此,因此要求人们帮助提供有限的信息并不能描绘出整个画面。所以答案是Fly 不再将IVerticalSpeed 实现为“IFlyable”所表示的属性

标签: c# inheritance interface


【解决方案1】:

所有答案都向您展示了可能的解决方案,但没有一个真正回答这里的重要问题:

我认为一切都应该没问题,因为我的ISpeed 接口是IVertialSpeed 接口+ISpeed 接口包含的任何东西。但这是不对的。我收到错误消息:“Fly 没有实现接口成员 IFlyable.Speed (...)。为什么?

你自己说过。 ISpeedIVerticalSpeed,但并非所有 IVerticalSpeeds 都是 ISpeeds 所以你根本不满足合同。

如果您的代码被允许并且我想要执行以下操作会发生什么:

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

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

您现在看到问题了吗?你会违反接口的约定,因为你的类只接受 ISpeed 而它应该接受 any IVerticalSpeed

【讨论】:

  • 另一种强调方式:合同被set 破坏,OP 正在推理get 部分。
【解决方案2】:

如果你使用泛型,你可以做类似的事情

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

然后在你的课堂上你会做类似的事情

public class Fly : IFlyable<SomeSpeedClass>
{
  public SomeSpeedClass Speed{get;set}
}

【讨论】:

  • 你认为飞机是垂直速度的飞机吗?仅仅因为它可能与泛型有关并不意味着它应该。老实说,这个特殊的例子似乎不适合泛型。
  • @InBetween 最好的方法是什么?因为Fly 类必须实现IFlyable 接口,但他希望在Speed 属性中返回ISpeed 的实例,而不是IVerticalSpeed 实例。
  • 如果没有上下文,我将无法回答最佳方法是什么。但可以合理地预期IFlyable 将具有与HorizontalSpeedHorizontalAccelerationVerticalAcceleration 等类似的属性。您要创建IFlyable&lt;T1, T2, T3, etc&gt; 接口吗?甚至让我们不要开始讨论如何处理泛型类型差异......这一切都很快变得非常混乱。泛型不应该只是让类型系统工作的解决方案。
【解决方案3】:

因为您的资源的签名必须保持 100% 不变。您可以实现一个新属性,作为一种解决方法。但它也有它的局限性。

如果你的继承可以双向工作,你可以这样做。你已经知道了,所有ISpeeds 都是IVerticalSpeeds。但反过来就不是这样了。并非所有IVerticalSpeeds 都是ISpeeds。所以我们可以给你的类提供另一种方法,但它会在那个时候遇到一个问题:

  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,您想做什么?因为你的界面说这是允许的。也许你不想要二传手?

【讨论】:

    【解决方案4】:

    代替

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

    你应该匹配IFlyable接口

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

    接口不是继承,必须完全匹配。

    编辑:让我换个说法,实现其他接口的接口不是继承,因此是错误的。接口必须完全匹配,这就是它引发错误的原因 (ISpeed != IVerticalSpeed)

    【讨论】:

    • 支持@InBetween,因为它更清楚,尽管两个答案都试图回答相同。
    【解决方案5】:

    您尚未显示IVerticalSpeed,但如果您可以控制它,请考虑

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

    然后像这样在Fly中实现

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-04
      • 1970-01-01
      • 2020-10-17
      • 2021-01-29
      相关资源
      最近更新 更多