【问题标题】:base class virtual method with an interface as argument cannot be overriden by an implementation [duplicate]具有接口作为参数的基类虚拟方法不能被实现覆盖[重复]
【发布时间】:2017-12-26 10:24:33
【问题描述】:

我有一个定义

的基类
public class BaseClass 
{
    public virtual bool StartUpdate( Interface )
    { some code here }
}

然后,有一个实现接口的类

public ClientClass : Interface {}

在派生类中

public class DerivedClass : BaseClass
{
    public override bool StartUpdate( ClientClass )
    { some code... }
} 

编译器 (c#) 在 DerivedClass 上引发错误,提示未找到合适的覆盖方法。 我做错了什么?为什么编译器不能注意到ClientClass 实现了Interface

任何帮助将不胜感激。

编辑:

找到一个“解决方案”

在基类中

public virtual bool StartUpdate( object o )
{
    checkInterface( o ); // if not o is Interface, throws an exception
    more code...
}

在派生类中

public override bool StartUpdate( object o )
{
    // o will always implement Interface 
}

这是一团糟,但 c# 喜欢它的方式。

【问题讨论】:

  • 请提供带有正确方法签名的实际代码
  • 为什么你需要具体的ClientClass作为参数,而不是interface
  • @marcelo - 为什么要这样使用object?你失去了拥有特定对象/接口的所有力量......这可以编译,但肯定不是“C#喜欢它”的方式......你甚至看过下面的答案吗?

标签: c# interface virtual


【解决方案1】:

您的基类方法签名是:

public virtual bool StartUpdate(Interface obj) { }

但是在你的派生类中你写了:

public override bool StartUpdate(ClientClass obj) { }

尽管ClientClass 实现了Interface,但它不是同一类型。您的方法在派生中的签名应该是Interface。来自MSDN中的规范:

被覆盖的基方法必须与覆盖方法具有相同的签名


如果您希望派生方法具有不同的具体类型,请考虑generics

public class BaseClass<T> where T : Interface 
{
    public virtual bool StartUpdate(T data) { /*code here*/ }
}

public class Derived : BaseClass<ClientClass> 
{
    public override bool StartUpdate(ClientClass data) { /*code here*/ }
}

【讨论】:

  • 当然,我尝试了通用方法。但是该基类与另一个基类(我的问题中未显示)有很多交互,这些基类被证明无法使用泛型。我正在尝试实现 MVP 模式(或类似的模式),因此我开发了 BasePresenter(我展示的类)和 BaseView(Form 的子类),因为(显然)两者之间有很多共同的功能。但我迷失了仿制药。谢谢。
  • 不客气 :) 听起来你的课程确实很大。将它们分解为具有适当接口和组合的小单元。然后在需要时使用泛型。至于没有实现接口的问题本身,这个答案为您提供了原因和解决方案(甚至在提到遗传学之前)
  • 遗憾的是,Form 派生类不是“可破坏的”(即使我将代码拆分为各种部分源)。 BasePresenter 类并没有那么大。但是 BaseView 有点复杂。这就是放弃泛型的原因。
【解决方案2】:

这可能是您正在寻找的:

public class BaseClass<T> where T: Interface
{
    public virtual bool StartUpdate(T input)
    {
        // return whatever
    }
}

public class DerivedClass : BaseClass<ClientClass>
{
    public override bool StartUpdate(ClientClass input )
    {
        // return whatever
    }
} 

【讨论】:

    【解决方案3】:

    在缩小您覆盖的方法的范围的同时,不可能覆盖一个方法。您必须接受所有类型的接口,否则您正在减少基类的功能,这是不允许的。所以你应该写:

    public override bool StartUpdate( Interface obj )
    

    这被称为Liskov substition principle

    【讨论】:

    • 在重写方法中使用该接口没有什么帮助,因为我必须在每个可以由基类处理的类中实现该接口,因为它必须调用其中定义的一些方法。请看我上面对吉拉德的评论。
    猜你喜欢
    • 2021-11-02
    • 1970-01-01
    • 2010-11-22
    • 2016-01-24
    • 2016-06-14
    • 2014-09-04
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多