2013-03-11 35 views
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>(); 
    } 
} 
+1

目前还不清楚你对哪个方面感到困惑。 – 2013-03-11 16:04:16

+0

我猜测它是受保护隐式实现的显式接口实现(如果这就是它 - 我会说隐式接口实现是公共的)。 – 2013-03-11 16:07:26

+0

我的歉意。混淆我的部分是我看作是IInterface.DoSomething返回虚拟DoSomething的私有实现的东西。我也注意到了IInterface。它是编译所必需的。 – Kirby 2013-03-11 16:10:13

回答

1

IEnumerable<object> IInterface.DoSomething() 

这就是所谓的explicit interface implementation

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

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

采取这种方法的原因之一是强制更好的编码实践。如果你是这个类的开发者,并且你知道它只能通过一个接口来访问,那么这就是迫使它发生的方法。

+0

我知道显式接口imp,并且我知道它在使用多个碰巧具有相同命名方法的接口时派上用场。我仍然不确定程序员为什么这样做,以及它给了什么好处。 – Kirby 2013-03-11 16:19:09

+1

这不仅仅是在有两个定义时使用一个接口;它是强迫类通过接口而不是直接使用类本身(即使只涉及一个接口)。我的答案显示了为什么要这样做的一个原因。 – 2013-03-11 16:21:37

+0

在C#中,你不能修改显式的接口实现 - 它总是私有的。在VB.NET中,我相信你可以明确地实现你想要的任何访问。就我个人而言,我更喜欢C#的方式。 – 2013-03-11 16:26:09

0

把我的头我有这个实际使用的思维麻烦的顶部,但有一两件事,这完成是MyBase类型的对象或它的子类没有publicinternal LY可见DoSomething()方法:

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

但是当对象被用作IInterfaceDoSomething()方法是可见的:

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

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

使0非显式版本允许子类覆盖DoSomething()方法的行为。

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

+0

有关使用的更多信息,在创建并返回MyClass的相同程序集中有一个工厂类。使用该MyClass的类也在同一个程序集中,它调用方法不存在的问题。示例var myClass = SomeFactory.GetMyClass(); myClass.DoSomething() – Kirby 2013-03-11 16:17:26

+0

带有该代码的类是否继承自“MyBase”? – JLRishe 2013-03-11 16:19:36

+0

这可能是因为'GetMyClass()'返回一个接口,而不是具体的myBase或myClass。 – 2013-03-11 16:20:07

0

我认为这是它所实现的模板模式here。通常您会看到与strategy模式一起使用的模板模式。在您的具体示例中,IInterface的用户可以调用方法,而不考虑具体子类如何实现该方法。

这种OO编程允许您利用其他一些模式,例如AbstractFactory创建MyBase的具体子类,它们实现IInterface

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 
    } 
} 

,但它可以让你在声明为MyClassMyBase,你可能不希望他们做一个变量调用DoSomething

+0

这个解释让我对事情变得更加清楚。你是否也同意nattyddubbs这看起来像模板模式?我将需要对这种模式进行一些阅读。 – Kirby 2013-03-11 16:32:27

+0

这似乎是正确的 - 以前从来没有将它称为模板模式,但这是非常简单的基于继承的OOP - 基类和子类中的重写方法,以使它们按照您希望的方式运行。 – 2013-03-11 16:47:39

+0

想通过投票给你道具,但我的代表还不够高。再次感谢您指出命名矿块! – Kirby 2013-03-11 18:31:32

0

在C#中,明确地使用它什么都不做的密封的方法实现一个接口,但调用一个受保护的虚拟方法允许派生类关于他们希望与界面做了很大的灵活性;该方法应该给出一个名称其他比接口方法的名称(在上面的例子中,它可能是DoSomething_Prot)。显式接口实现使得派生类重新实现不可能链接到基类实现,但是如果基类实现正在做的唯一事情是链接到受保护的虚拟或抽象方法,则不需要派生类类来重新实现接口。此外,即使派生类要故意地或作为协方差的结果重新实现接口,它仍然能够使用基类中的受保护方法调用基类实现的“胆量”。

把所有的代码,其中隐式地实现接口是不是把代码中的显式实现更好,因为衍生类代码可以通常是链到私有成员公共虚拟方法的接口实现。然而,这种方法要求所有派生类公开实施具有相同签名的方法。虽然看起来好像人们自然会期望的那样,但并不总是如此。例如,在上面的例子中派生类可能希望有其DoSomething方法返回比IEnumerable<object>以外的类型(例如它可能返回IList<Kangaroo>)。实现interfae的方法仍然必须返回精确的类型IList<Kangaroo>,但是知道它的代码是处理派生类型的,可以使用返回类型作为IList<Kangaroo>而不使用类型转换。如果该方法的实际代码放在一个称为DoSomething_Prot()方法,派生类都可以重写DoSomething_Prot并声明new public IList<Kangaroo> DoSomething()。如果基类方法被称为DoSomething(),那么派生类就不可能覆盖它并定义一个具有不同返回类型的新方法。