假设我有一个简单的抽象基类
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)
在您继续阅读之前,请认真:尝试预测此计划的输出.
现在实际运行它.你有没有得到预期的输出?你的直觉在哪里错了?
你看到CharlieOne和CharlieTwo现在之间的区别? 重新实现IFoo在CharlieTwo可导致接口绑定拿起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
| 归档时间: |
|
| 查看次数: |
6340 次 |
| 最近记录: |