3

今天我遇到了一个问题,试图覆盖一个没有被声明为虚拟的接口方法的实现。

在这种情况下,我无法更改接口或基本实现,必须尝试其他方法,但我想知道是否有办法强制类使用虚拟方法实现接口。

例子:

interface IBuilder<T>
{
    // Already implicitly virtual
    /*virtual*/ T Build();
}

// This is a class written by someone else
class SimpleBuilder: IBuilder<SomeObject>
{
    // I would like to force this to be virtual
    public SomeObject Build() { return new SomeObject(); }
}

// This is the class I am writing.
class CustomBuilder: SimpleBuilder
{
    public /*override*/ SomeObject Build()
    {
        var obj = base.Build();
        obj.ModifyInSomeWay();
        return obj;
    }
}

编辑:CustomBuilder旨在与 MEF 一起使用,因此我是从中派生的SimpleBuilder,以便 MEF 解析正确的类型。我已经尝试显式地实现接口并且根本不派生,SimpleBuilder但是 MEF 没有选择正确的类型。

有问题的接口和基类位于另一个开发人员创建的共享模块中,所以看起来我无论如何都必须让他们改变他们的基类。

4

5 回答 5

3

不,没有,在您的示例中,您正在隐式实现接口。如果您的类要被子类化并且方法被覆盖,则由开发人员确保该方法被标记为虚拟方法。

没有办法强制接口方法的实现在代码中是可覆盖的,只有开发团队中的约定可以确保这一点(例如,所有接口都应该显式实现,所有接口实现都应该标记为虚拟等)。

在此特定示例中,您可以将抽象类插入层次结构:

abstract class VirtualBuilder<T> : IBuilder<T>
{
  abstract T Build();
}

但这不适用于通用情况,因为您失去了接口的好处,并且“强制”所有具体类只实现一个接口。

于 2012-07-03T10:44:36.487 回答
2

不直接,不。

您可以通过提供自己的基类并要求用户从中派生来“强制”它:

abstract class BuilderBase<T> : IBuilder<T>
{
    public abstract T Build();
}

但这也有严重的问题,因为

  1. 它不会立即阻止任何人直接实现接口(尽管您可以例如要求传入的参数BuilderBase<T>而不是简单的IBuilder<T>,或者甚至IBuilder<T> internal在另一个程序集中制作和隐藏它)
  2. 它迫使接口的实现者放弃他们对单个基类的选择,他们可能会讨厌你
于 2012-07-03T10:47:37.140 回答
1

你不能强制它是虚拟的,但你可以使用 new 关键字;它被称为方法隐藏

// This is the class I am writing. 
class CustomBuilder: SimpleBuilder, IBuilder<T> 
{ 
    public new SomeObject Build() 
    { 
        var obj = base.Build(); 
        obj.ModifyInSomeWay(); 
        return obj; 
    } 
} 
于 2012-07-03T10:44:25.610 回答
0

无法指定如何实现接口方法。

但是,即使基本实现不是虚拟的,您也有两种方法可以在子类上重新实现接口方法:

  • new使用方法限定符隐藏基本实现,或
  • 像这样的显式接口实现:

    T IBuilder.Build() { var obj = Build(); obj.ModifyInSomeWay(); 返回对象;}

这些方法中的任何一种都将确保仅在通过接口访问您的类时才调用您的方法,但如果调用使用基类引用则不会。

所以我想说这个基类还没有准备好通过继承进行扩展。

于 2012-07-03T10:47:51.737 回答
0

您不能这样做,因为接口只描述了类的外观,而没有说明实现本身。

换句话说,如果您使用的类实现了定义方法的接口,Foo()则可以确定,无论实现如何,该类都具有此方法。

你可以做什么:

public interface IBuilder<T>
{
    T Build();
}

public abstract class BaseBuilder<T> : IBuilder<T>
{
    public abstract T Build();
}

public class CustomBuilder : BaseBuilder<CustomBuilder>
{
    public override CustomBuilder Build()
    {
        throw new NotImplementedException();
    }
} 
于 2012-07-03T10:51:28.410 回答