【问题标题】:Interface implementation with abstract class input parameters带有抽象类输入参数的接口实现
【发布时间】:2017-12-27 06:53:31
【问题描述】:

我想了解接口实现,因为我遇到了对我来说没有意义的错误。 我有这个接口和 2 个抽象类:

public interface ICashBuddieHelper
{
    IHelper FilterOnContext(DbBuddieContext db);
    IHelper PrepareResultModel(InputModelBase message);
    IHelper SortSet();
    ResultModelBase ToResultModel(InputModelBase message);
}

public abstract class ResultModelBase
{
    ...
}

public abstract class InputModelBase
{
    ...
}

我有两个类实现了这个 Helper 接口,但具有更多派生版本的输入参数和返回类型,它们是抽象类,如上所示。 我已经使用以下类实现了 IHelper 接口

public class BankAccountHelper : ICashBuddieHelper
{
    public ICashBuddieHelper FilterOnContext(DbBuddieContext db){...}
    public ICashBuddieHelper PrepareResultModel(BankAccountInputModel message){...}//error
    public ICashBuddieHelper SortSet(){...}
    public ResultModelBase ToResultModel(BankAccountInputModel message){...}//error
}

public class CashFlowHelper : ICashBuddieHelper
{
    public ICashBuddieHelper FilterOnContext(DbBuddieContext db){...}
    public ICashBuddieHelper PrepareResultModel(CashFlowInputModel message){...}//error
    public ICashBuddieHelper SortSet(){...}
    public ResultModelBase ToResultModel(CashFlowInputModel message){...}//error
}

从上面的代码 sn-p 中,你可以看到实现类中的两行给出的错误是:

“CashFlowHelper”没有实现接口成员“ICashBuddieHelper.PrepareResultModel(InputModelBase)” “CashFlowHelper”没有实现接口成员“ICashBuddieHelper.ToResultModel(InputModelBase)”

请有人告诉我我做错了什么吗?我想了解我对接口的误解。当然,我可以使用更派生的类型来代替抽象类。我不明白编译器在抱怨什么。

【问题讨论】:

  • 您在 CashFlowHelper 中缺少 public(在接口方法签名前面)。该界面要求它们是公开的。
  • 添加到@john 的答案:如果要隐藏接口成员,请明确说明。例如,void IMyInterface.DoSomething { }
  • 对不起,约翰,我在 stackoverlow 上添加时不只是添加 public。我现在将其添加到其中。谢谢
  • 仅供参考您的代码似乎工作正常。见fiddle。有时当我在实现类等时,我按下Ctrl+.,然后点击Enter,因为我走得太快,我不小心在本地命名空间中得到了一个与类同名的新类在另一个命名空间中。你有机会做到这一点吗?还是有可能实现和接口引用了两个不同的同名类?
  • @JosephIzang 目前状态的问题尚不清楚,因为它不完整,需要太多问题才能澄清所问的问题。阅读How to Ask,然后提供minimal reproducible example,可用于重现您的问题,让我们更好地了解所要求的内容。

标签: c#


【解决方案1】:

当然,我可以使用更派生的类型来代替抽象 班级。我不明白编译器在抱怨什么。

引用interface (C# Reference)

一个接口只包含方法、属性的签名, 事件或索引器。实现接口的类或结构 必须实现接口定义中指定的接口成员

注意:强调我的

接口是任何派生类都必须遵循的契约。

编译器不做任何假设

ICashBuddieHelper PrepareResultModel(InputModelBase message);

public ICashBuddieHelper PrepareResultModel(BankAccountInputModel message)

不管BankAccountInputModel 是从InputModelBase 派生的。

就编译器而言,这是两个不同的定义,并且您因未按定义实现接口而违反了合同。因此编译错误。

那么我可以在哪里使用我的派生类型,即 BankAccountInputModel?或者 而是如何在接口中使用基本类型并开始使用 该类型的更多派生版本?

您可以考虑的一种可能性是使用Generics (C# Programming Guide),这本身就是另一个主题,但请查看以下示例,该示例重构了接口并使用了您之前定义的类型。

public interface ICashBuddieHelper<T> where T : InputModelBase {
    ICashBuddieHelper<T> FilterOnContext(DbBuddieContext db);
    ICashBuddieHelper<T> PrepareResultModel(T message);
    ICashBuddieHelper<T> SortSet();
    ResultModelBase ToResultModel(T message);
}


public class BankAccountInputModel : InputModelBase {
    //...
}

public class BankAccountHelper : ICashBuddieHelper<BankAccountInputModel> {
    public ICashBuddieHelper<BankAccountInputModel> FilterOnContext(DbBuddieContext db) { return null; }
    public ICashBuddieHelper<BankAccountInputModel> PrepareResultModel(BankAccountInputModel message) {
        return null;
    }
    public ICashBuddieHelper<BankAccountInputModel> SortSet() { return null; }
    public ResultModelBase ToResultModel(BankAccountInputModel message) {
        return null;
    }
}

每一项都可能增加不必要的复杂性。

我建议检查您的设计选择。

【讨论】:

    【解决方案2】:

    您的类实际上并不是从接口派生的,请在每个类中添加:IHelper,如下所示:

    public class BankAccountHelper : IHelper
    

    【讨论】:

    • 再次抱歉我的错误。应该是有点没睡吧。我很抱歉。我现在就改一下。
    猜你喜欢
    • 2012-07-17
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 1970-01-01
    • 2014-08-18
    • 1970-01-01
    • 2014-02-05
    • 1970-01-01
    相关资源
    最近更新 更多