【问题标题】:Override a method from a base class that explicitly implements an interface覆盖显式实现接口的基类中的方法
【发布时间】:2012-12-04 20:15:54
【问题描述】:

[编辑]

由于比原始帖子所需的复杂性略高——对此我深表歉意——我将尝试简化一下。

最初,我有一个看起来像这样的基类:

public class OurViewModel
{
  public bool Validate(ModelStateDictionary modelState){...}
}

我的类继承并隐藏了该方法,使用 new 关键字:

public class MyViewModel : OurViewModel
{
  public new bool Validate(ModelStateDictionary modelState) {...}
}

同时,IValidatableObject 接口出现了:

public interface IValidatableObject
{
  IEnumerable<ValidationResult> Validate(ValidationContext validationContext);
}

现在,OurViewModel(很遗憾)也发生了变化。它看起来像这样:

public class OurViewModel : IValidatableObject
{
  IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext) {..}
}

我现在需要做的是再次在 MyViewModel 中隐藏 Validate 方法,但我不知道如何使用当前的安排来实现。有什么好的办法吗?

(FWIW,我同意向基类添加新接口并不是完成工作的最佳方式,但这就是这里发生的事情。)


[原帖]

我在覆盖我的一个类中的方法时遇到问题。有人从这个改变了基类的继承模型:

public class OurViewModel : IntlViewModelBase<OurResources>

到这里:

public class OurViewModel : IntlViewModelBase<OurResources>, IValidatableObject

IValidatableObject 有一个方法签名,Validate():

IEnumerable<ValidationResult> Validate(ValidationContext validationContext);

OurViewModel 有一个 Validate 方法,如下所示:

public bool Validate(ModelStateDictionary modelState)

...现在是更改后的样子:

IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)

与此同时,我的类继承自 OurViewModel。它使用new 关键字来实现自己的布尔版本的Validate。

似乎我不再能够隐藏 Validate 方法,因为我的类没有实现 IValidatableObject。我现在覆盖该方法的正确方法是什么?

【问题讨论】:

  • 您似乎曾经能够覆盖该方法。不是virtual
  • 我在我的方法中使用了new 关键字来实现我自己的版本——也许我不应该在我的描述中使用“覆盖”这个词。这次我似乎无法使用new,所以听起来我必须将基本方法设为虚拟?
  • @larryq 那么你是想使用IValidatableObjectValidate的基类实现,还是你自己的?另外,您是否有权修改基类?
  • new 不会覆盖 - 它隐藏基类方法。
  • 我知道这并不能解决您当前的问题,但这对我来说听起来像是一个流程问题。应提前提出类继承层次结构的更改,并在实施之前在整个团队中进行讨论。

标签: c# inheritance interface


【解决方案1】:

我可能完全忽略了这一点,但这对我来说编译得很好(为OurResourcesIntlViewModelBase&lt;T&gt; 使用了存根类)。

public class OurViewModel : IntlViewModelBase<OurResources>, IValidatableObject
{
    public bool Validate(ModelStateDictionary modelState)
    {
        throw new NotImplementedException();
    }

    IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
    {
        throw new NotImplementedException();
    }
}

public class MyViewModel : OurViewModel
{
    public new bool Validate(ModelStateDictionary modelState)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 我的原始帖子中可能没有说清楚。对于那个很抱歉。发生的事情是 Validate 的 bool 版本现在消失了,取而代之的是 IValidateableObject.Validate 版本。
  • @larryq 那么你在子对象上根本不需要new,因为它没有任何阴影方法。您还没有真正描述您需要做什么,以及目前不起作用的情况。
【解决方案2】:

如果要覆盖新的Validate方法(IValidatableObject.Validate),只需添加virtual关键字即可。

public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

【讨论】:

  • 编译器告诉我,“虚拟”对于显式接口实现无效。
  • 将 virtual 添加到基类 OurViewModel 中的方法中。
  • 我明白你在说什么。需要明确吗? (例如,您可以将 OurViewModel 中的方法声明为:“public virtual IEnumerable Validate(ValidationContext validationContext)”)
  • @aprescott virtual 在显式接口实现上毫无意义,这就是编译器禁止它的原因。它永远不能被遮蔽或覆盖,因此virtual 的概念不适用。
【解决方案3】:

我想我已经把这个问题回答得够多了,并决定用这里提供的更简单的版本再试一次--this one

感谢所有回复的人。管理员可以关闭此线程或将其瞄准/链接到新问题吗?我不确定在这种情况下的 SO 网络礼节是什么。

【讨论】:

    【解决方案4】:

    几件事:

    1.

    如果您希望对基类中的每个方法都有新的 在派生类中实现然后派生没有意义 从基地。继承的主要目的是代码重用。所以你可以简单地从父子关系中删除关系。

    2.

    让我们假设在你的基类中有一些方法是 实际上继承。在那种情况下,我不认为应该有一个 用虚拟标记基类的接口成员的问题 关键字并在派生类中说它是新的。

    --

    如果您询问实现这种情况的不同方法,那么 我们需要知道你的目标是什么。如果目标是派生成员 有新的定义然后更好的方法是明确的 在派生类中实现接口。

    请提及您面临的确切问题?是您无法使用新关键字还是您正在寻求不同的方法来解决这种情况。

    【讨论】:

    • 继承的主要“正确”用法是可替换性。对于代码重用来说,封装一般比较好。
    • 对我来说,可替换性意味着 Lion 应该能够被视为 Animal 并且我们可以传递 Animal 对象而不用担心里面的实际类型......它是真的,可替换性是继承的重要用法,但是然后这个概念的名称应该是替代而不是继承。继承意味着派生可以使用基本成员功能..即。他们继承了它。
    • 继承提供代码重用和可替换性。在需要代码重用的情况下,封装通常更好。在没有可替代的东西需要重用任何实现细节的情况下,接口通常比抽象类更好。我的观点是,如果想要将一种类型的实例提供给需要另一种实例的代码,这是一个很好的迹象,即前一种类型应该从后者继承即使它替换了每个成员
    • 看起来与每个开发人员都相关。对我来说,代码重用是继承的主要目的,可替代性是次要的(可能是)。我严重怀疑封装能否实现代码重用。
    猜你喜欢
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 2014-11-20
    • 1970-01-01
    • 2012-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多