实现接口的抽象基类

woo*_*gie 24 c#

假设我有一个简单的抽象基类

abstract class Item : IDisplayable
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public abstract void Print();

    }
Run Code Online (Sandbox Code Playgroud)

我有一个继承自那样的类

  class Chair: Item
 {
    public int NumberOfLegs {get;set;}

    public void Print()
    {
     Console.WriteLine("Here is a simple interface implementation");
    }
 }

interface IDisplayable
{
void Print();
}
Run Code Online (Sandbox Code Playgroud)

子类没有明确地说它也实现了接口,但它将通过简单的继承来实现.如果我们将接口显式添加到子类,程序将运行相同的程序(至少在我的简单示例中可以告诉我).明确地实现界面是一个好的或坏的想法,还是严格来说是一个偏好的问题?

Eri*_*ert 43

如果我们将接口显式添加到子类,程序将运行相同的程序(至少在我的简单示例中可以告诉我).

该计划不一定会运行; 你的例子不足以说明差异.

明确地实现界面是一个好的或坏的想法,还是严格来说是一个偏好的问题?

除非您打算确保接口重新实现语义,否则这是一个坏主意.

让我简单说明一下.这个程序做什么用的?

using System;
interface IFoo { void Bar(); void Baz(); }
class Alpha : IFoo
{ 
    void IFoo.Bar() 
    {
        Console.WriteLine("Alpha.Bar");
    }
    void IFoo.Baz()
    {
        Console.WriteLine("Alpha.Baz");
    }
}
class Bravo : Alpha
{
    public void Baz()
    {
        Console.WriteLine("Bravo.Baz");
    }
}
class CharlieOne : Bravo
{
    public void Bar() 
    {
        Console.WriteLine("CharlieOne.Bar");
    }
}
class CharlieTwo : Bravo, IFoo
{
    public void Bar() 
    {
        Console.WriteLine("CharlieTwo.Bar");
    }
} 
class Program
{
    static void Main()
    {
        IFoo foo = new Alpha();
        foo.Bar();
        foo.Baz();
        foo = new Bravo();
        foo.Bar();
        foo.Baz();
        foo = new CharlieOne();
        foo.Bar();
        foo.Baz();
        foo = new CharlieTwo();
        foo.Bar();
        foo.Baz();
     }
}
Run Code Online (Sandbox Code Playgroud)

在您继续阅读之前,请认真:尝试预测此计划的输出.

现在实际运行它.你有没有得到预期的输出?你的直觉在哪里错了?

你看到CharlieOneCharlieTwo现在之间的区别? 重新实现IFooCharlieTwo可导致接口绑定拿起Bravo.Baz即使Bravo没有没有重新实现IFoo!

另一方面:如果您希望Bravo.Baz仅因为它存在而被分配到接口插槽,那么您将看到未能重新实现接口导致代码不正确.对于Bravo.Baz更换Alpha.IFoo.Baz,Bravo必须重新实现IFoo.

这里要说的是:当你重新实现一个接口时,所有的接口绑定都是从头开始重新计算的.这可能会导致程序中的语义更改,因此只有在您打算这样做时才重新实现接口.

这也说明了脆弱基类失败的另一种形式.假设你写的时Bravo没有方法.如果你写作重新实现,那么之后添加的作者 - 也许是你公司的不同团队的作者- 改变了界面绑定,即使这不是作者想要的. BazCharlieCharlieIFooBravoBaz BravoCharlieBravo

有关更多信息,请参阅我关于此主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2011/12/08/so-many-interfaces-part-two.aspx