1

我遇到了一些代码,不太确定它为什么会起作用,或者你为什么要这样做。如果有人能为我拆掉它,我会很高兴的。我确实很了解 OOP 概念,我以前从未见过这种技术。谢谢

这是示例:

public interface IInterface
{
    IEnumerable<object> DoSomething();
}

public abstract class MyBase : IInterface
{
    protected MyBase()
    {
    }

    IEnumerable<object> IInterface.DoSomething()
    {
        return DoSomething();
    }

    protected virtual IEnumerable<object> DoSomething()
    {
        return new List<object>();
    }
}

public class MyClass : MyBase
{
    internal MyClass() : base() {}

    protected override IEnumerable<object> DoSomething()
    {
          return new List<object>();
    }
}
4

5 回答 5

1

如果您在谈论这行代码:

IEnumerable<object> IInterface.DoSomething()

这称为显式接口实现

这迫使消费者只能通过接口访问此方法,而不是直接访问您的类。

上述方法不是私有的,只是没有在代码中明确设置为公共。事实上,通过显式接口实现,您甚至不能使用访问修饰符。

采用这种方法的原因之一是强制更好的编码实践。如果您是此类的开发人员,并且您知道只能通过接口访问它,那么这就是强制实现的方法。

于 2013-03-11T16:10:46.023 回答
0

在我的脑海中,我很难想到它的实际用途,但是这样做的一件事是类型的对象MyBase或其子类没有publicinternal可见的DoSomething()方法:

MyClass a = new MyClass();
a.DoSomething();  // Compile error

但是DoSomething()当对象被用作时,该方法是可见的IInterface

void AMethod(IInterface i)
{
    i.DoSomething(); // compiles just fine
}

void AnotherMethod(MyBase a)
{
    AMethod(a); // as does this
}

制作非显式版本protected virtual允许子类覆盖DoSomething()方法的行为。

MyBase这是一种实现方法的方法,在使用s as s时不能直接调用MyBase,但可以在将它们视为 s 时使用IInterfaces。没有什么可以阻止某人这样做:((IInterface)a).DoSomething();但似乎隐藏是出于语义原因。

于 2013-03-11T16:14:19.680 回答
0

我对此的看法是,它是此处描述的模板模式的实现。通常,您会看到与策略模式一起使用的模板模式。在您的特定示例中,用户IInterface可以调用该DoSomething 方法而不考虑具体子类如何实现该方法。

这种 OO 编程允许您利用很多其他模式,例如 AbstractFactory 来创建您的具体子类,MyBase其中实现IInterface.

于 2013-03-11T16:19:22.850 回答
0

需要注意的重要一点是,这两种DoSomething方法彼此无关——它们只是碰巧有相同的名称。

基本上,您只是获得了一个公开DoSomething方法的普通接口,因此拥有IInterface对象的调用者可以调用它。然后它将依次将调用传递给受保护DoSomething方法的适当实现,该方法可以来自基类或派生类。

像这样的显式实现会迫使您通过合同而不是实现来编码 - 并没有真正提供任何实际的保护,只是让您在声明变量时更难意外使用错误的类型。他们可以很容易地做到:

public abstract class MyBase : IInterface {
    public virtual IEnumerable<object> DoSomething() {
       // blah
    }
}

public class MyClass : MyBase {
    public override IEnumerable<object> DoSomething() {
        // blah
    }
}

但这会让您调用DoSomething声明为MyClassor的变量MyBase,您可能不希望他们这样做。

于 2013-03-11T16:24:43.957 回答
0

在 C# 中,通过使用除了调用受保护的虚方法什么都不做的密封方法来显式实现接口允许派生类在他们想要对接口做什么方面具有很大的灵活性;该方法应命名为other而不是接口方法的名称(在上面的示例中,它可能是 DoSomething_Prot)。显式接口实现使得派生类的重新实现不可能链接到基类实现,但是如果基类实现唯一要做的就是链接到受保护的虚拟或抽象方法,则不需要派生类类来重新实现接口。此外,即使派生类有意或由于协变而重新实现接口,它仍然能够使用基类中的受保护方法调用基类实现的“胆量”。

将接口实现的所有代码放在隐式实现接口的公共虚拟方法中比将代码放在显式实现中要好,因为派生类代码通常可以链接到私有成员。然而,这种方法要求所有派生类公开实现具有相同签名的方法。尽管这似乎是人们自然期望的结果,但并非总是如此。例如,在上面的例子中,一个派生类可能希望它的DoSomething方法返回一个非类型IEnumerable<object>(例如它可能返回一个IList<Kangaroo>)。实现接口的方法仍然必须返回精确类型IList<Kangaroo>,但是知道它正在处理派生类型的代码可以使用返回类型作为IList<Kangaroo>没有类型转换。如果该方法的实际代码在一个名为 的方法中DoSomething_Prot(),则派生类可以覆盖DoSomething_Prot和声明一个new public IList<Kangaroo> DoSomething(). 如果调用了基类方法DoSomething(),则派生类将无法同时覆盖它并定义具有不同返回类型的新方法。

于 2013-03-11T16:45:04.893 回答