在Base类中声明的C#接口方法不需要在Derived类中再次实现

时间:2013-11-11 15:46:26

标签: c# .net oop c#-4.0

这可能是一个愚蠢的问题,但我正在学习,我只是好奇发生了什么,今天我正在玩几个oops概念并在VS中学习它。我再次感到困惑的是,我们不必在派生类中实现多个接口相同的方法,其中ACTUALLY我们“继承”接口,但是在基类中。

我可以知道它是如何工作的吗?我担心的是,即使我没有在基类中“继承”接口方法,我也使用同名的方法。我也没有在派生类中实现它。

有人可以帮我理解发生了什么以及如何以及为什么?

Class A
{
    public void Display()
    {
        Console.Writeline("I am from A");
    }
}

interface IA
{
    void Display();
}

interface IB
{
    void Display();
}

Class B : A, IA, IB
{

}

Class Final
{
    static void Main()
    {
        B b = new B();
        b.Display(); // displays class A Display method.
        Console.Readline();
    }
}

4 个答案:

答案 0 :(得分:3)

原因是因为实现是“隐含的” - 接口的隐式实现。

Class A
{
 public void Display()
 {
     Console.Writeline("I am from A");
 }
}

interface IA
{
 void Display();
}

interface IB
{
 void Display();
}

Class B : A, IA, IB
{
  void AI.Display() { Console.Writeline("I am from AI.Display"); }
}

Class Final
{
 static void Main()
 {
   B b = new B();
   b.Display(); // displays class A Display method.
   (b as IB).Display(); // displays class A Display method.
   (b as AI).Display(); // displays AI.Display
   Console.Readline();
 }
}

上面的示例现在具有接口方法显示的显式实现。请注意方法签名的轻微变化 - 这是您声明显式实现的方式,该实现在接口表示对象时特别使用,在本例中为(b as AI)

否则,如果方法签名匹配,则自动(隐式)使用它作为接口的方法。

答案 1 :(得分:3)

虽然我不能代表语言团队发言,但您可以通过提出替代解决方案来回答这个问题。

您想知道为什么B被认为是实现接口IA,即使所需的方法定义在基类A中,也没有实现接口。所以,让我们考虑相反的情况:B

这意味着您的代码无法编译。为什么不编译?由于B未实现接口Display所需的成员IA

要解决此问题,您需要向类Display添加方法B。这修复了接口实现。但是,您现在遇到了一个新的编译问题:您将看到警告“B.Display()”隐藏继承的成员'ConsoleApplication1.A.Display()'。如果想要隐藏,请使用new关键字。“

这是因为您的A.Display无法覆盖 - 而且您不想覆盖它。如果你选择的话,你可以实现一个方法来调用base.Display(),但是这是额外的代码,基本上什么都不做,并且它使你的继承变得混乱,因为new方法的处理方式不同于覆盖。 (如果您编写A x = new B(); x.Display();,那么您实际上会直接调用A.Display(),这可能会因您的代码发展而变得混乱,并且等待发生事故。)

或者,您可以实现一个全新的B.Display方法。您现在所做的是隐藏在A类中实现的方法,可能来自可能派生自B或创建B实例的任何人。使用new隐藏方法很少是可理解的对象结构的一个配方,这也不例外 - 所有这些都可以让你干净地实现一个接口。

所以最终,我想,这个决定是因为替代方案过于混乱。

答案 2 :(得分:1)

在你的情况下发生的事情是,B类通过继承A类适当的IA方法实现这一事实来满足IA接口契约。

答案 3 :(得分:1)

查看它的方法是 - 接口是契约(它没有实现)因此它只是要求任何实现类定义它在契约中定义的所有相同成员。

在您的情况下,您的界面Display中有1个方法,您的类B是实现此界面的唯一类,并且显式未定义实现Display(也许这就是你的困惑所在)。但是,它继承自A 为其定义实现,因此B默认实现接口。