【问题标题】:Interface inheritance consistency接口继承一致性
【发布时间】:2012-03-26 12:33:44
【问题描述】:

先看这段代码:

class Program
{
  static void Main(string[] args)
  {
    var x =(Base) new Derived();
    ((IMethod)x).DoWork();

    Console.ReadKey();
  }
}

interface IMethod
{
  void DoWork();
}

abstract class Base : IMethod
{
  void IMethod.DoWork()
  {
    Console.WriteLine("Base.DoWork");
  }
}

class Derived : Base, IMethod
{
  public void DoWork()
  {
    //here I where I want to call base.DoWork();
    Console.WriteLine("Derived.DoWork"); 
  }
}

输出:

Derived.DoWork

期望:

Base.DoWork
Derived.DoWork

我正在处理一个 API,它公开了一个接口,当实现该接口时,DoWork 方法将在进程的某个部分被调用。

现在在上面的例子中,Base 类是 API 的一部分,它在内部(在 API 中)已经显式地实现了该接口并在 DoWork 方法中执行了一些重要的操作。

我还需要在我的派生类中重写IMethod 的实现,所以我会在需要时收到通知,问题是我不能“重写”该方法并调用基方法,我也不能转换以IMethod为基础。

有什么办法吗?

注意:反射不起作用,因为它是 Silveright 项目,并且禁止调用私有方法。

【问题讨论】:

  • 为什么要混合两种接口实现方式?
  • 您的基类显然没有考虑到这种继承;通常,如果基类希望允许覆盖行为,则基类将提供一个受保护的虚拟方法来实现显式实现的逻辑。鉴于此,即使您能找到一种方法,“强制”这种覆盖行为也是有风险的,因为您实际上是以原始开发人员未设计的方式从类派生的。也就是说,这仍然是一个有趣的问题。
  • @DanBryant,让我们把设计放在一边(除此之外别无选择),但不要忘记我需要像基类一样实现接口,并且两种方法都必须叫做。请参阅我的更新答案。
  • @DanBryant,实际上你的解决方案就是我要做的,我将在基础中调用一个受保护的虚拟方法并在派生中覆盖它。请张贴作为答案。

标签: c# silverlight inheritance interface implementation


【解决方案1】:

您在寻找:

public class Derived : Base
{
    public override void DoWork()
    {
        base.DoWork();
    }
}

【讨论】:

  • 那不行; Base 实际上没有名为 DoWork() 的方法。
  • 啊,你是对的。我没有注意到它使用了接口实现。 @Shimmy 是否可以将方法的定义更改为显式实现接口(例如,public virtual void DoWork())?
【解决方案2】:

您是否能够只编写类而不使用继承?然后你可以随意实现DoWork(),并且仍然在Base对象上调用DoWork()。由于Base 是抽象的,因此您需要派生一个虚拟类型才能使一切正常工作。

class Derived : IMethod
{
    private class SneakyBase : Base
    {
        // abstract implementations here
    }

    private IMethod baseObject = new SneakyBase();

    void DoWork()
    {
        baseObject.DoWork();

        // Custom DoWork code here
    }
}

这样做显然有点痛苦,但是 API 设计者在显式接口实现方面做出了一个奇怪的选择,而你现在为此付出了代价。

【讨论】:

  • 不。基类是抽象的!此外,在我的场景中,我必须重写它。
【解决方案3】:

我发现DanBryant's comment 是答案,尽管正如他提到的那样有点冒险,因为我们不能保证实现者会调用基本方法,但这是一个不错的方法。

我创建了一个从私有接口实现者调用的受保护的虚拟方法,然后,在派生类中,我不用担心接口,只关心重写基类并从中调用基实现,这样就可以了完美,例如:

abstract class Base : IMethod
{
  void IMethod.DoWork()
  {
    DoWork();
  }

  protected virtual void DoWork()
  {
    Console.WriteLine("Base.DoWork");
  }
}

class Derived : Base
{
  protected override void DoWork()
  {
    base.DoWork();
    //here I where I want to call base.DoWork();
    Console.WriteLine("Derived.DoWork");
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-10
    • 2020-02-07
    • 1970-01-01
    • 2013-10-22
    • 2021-09-12
    • 2010-09-21
    相关资源
    最近更新 更多