接口和抽象类保护级别方法

时间:2013-03-11 16:03:11

标签: c# oop class interface protected

我遇到了一些代码,我不太确定它为什么会起作用,或者为什么你想这样做。如果有人能为我撕下它,我会很高兴。我确实理解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>();
    }
}

5 个答案:

答案 0 :(得分:1)

如果您正在谈论这行代码:

IEnumerable<object> IInterface.DoSomething()

这叫做explicit interface implementation

  

迫使消费者仅通过界面访问此方法,   而不是直接上课。

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

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

答案 1 :(得分:0)

在我的头脑中,我无法考虑实际用途,但这样做的一件事是MyBase类型的对象或其子类没有{{1} }或public可见internal方法:

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时无法直接调用的方法,但可以在将它们视为MyBase时使用。没有什么可以阻止某人这样做:IInterfaces但似乎隐藏是出于语义原因。

答案 2 :(得分:0)

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

这种OO编程允许您利用其他一些模式(如AbstractFactory)来创建实现MyBase的{​​{1}}的具体子类。

答案 3 :(得分: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
    }
}

但是,您可以在声明为DoSomethingMyClass的变量上调用MyBase,您可能不希望他们这样做。

答案 4 :(得分:0)

在C#中,通过使用密封方法显式实现接口,该方法除了调用受保护的虚拟方法之外什么都不做,允许派生类在他们想要对接口做什么方面具有很大的灵活性;该方法应该被赋予一个名称​​ other 而不是接口方法的名称(在上面的例子中,它可能是DoSomething_Prot)。显式接口实现使得派生类重新实现不可能链接到基类实现,但如果基类实现正在做的唯一事情是链接到受保护的虚拟或抽象方法,则不需要派生类重新实现接口。此外,即使派生类要么故意地或者作为协方差的结果重新实现接口,它仍然能够使用来自基类的受保护方法来调用基类实现的“胆量”。 p>

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