在C#中使用抽象类的接口

时间:2009-03-26 01:58:32

标签: c# inheritance interface abstract-class

我正在学习来自C ++的C#并且遇到了障碍。

我有一个抽象类AbstractWidget,一个接口IDoesCoolThings,以及一个派生自AbstractWidget的类,名为RealWidget:

public interface IDoesCoolThings
{
    void DoCool();
}

public abstract class AbstractWidget : IDoesCoolThings
{
    void IDoesCoolThings.DoCool()
    {
        Console.Write("I did something cool.");
    }
}

public class RealWidget : AbstractWidget
{

}

当我实例化一个RealWidget对象并在其上调用DoCool()时,编译器给出了一个错误说

  

'RealWidget'不包含   'DoCool'的定义

我可以将RealWidget对象转换为IDoesCoolThings,然后调用就可以了,但这似乎是不必要的,我也失去了多态性(即使我定义了RealWidget.DoCool(),也总是会调用AbstractWidget.DoCool())。

我想解决方案很简单,但我尝试了各种各样的事情,因为我的生活无法解决这个问题。

4 个答案:

答案 0 :(得分:42)

您遇到了问题,因为您使用了 explicit interface implementation (EII)。当显式实现成员时,不能通过类实例访问它 - 只能通过接口的实例访问它。在您的示例中,这就是为什么除非您将实例强制转换为DoCool(),否则无法致电IDoesCoolThings

解决方案是公开DoCool()并删除显式接口实现:

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()      // DoCool() is part of the abstract class implementation.
    {
        Console.Write("I did something cool.");
    }
}

// ...

var rw = new RealWidget();
rw.DoCool();                  // Works!

通常,您在两种情况下使用EII:

  • 您有一个必须实现两个接口的类,每个接口都包含一个与另一个接口中另一个成员具有相同名称/签名的成员。
  • 您希望强制客户端不依赖于您的类的实现细节,而是依赖于您的类实现的接口。 (这被一些人认为是一种很好的做法。)

答案 1 :(得分:8)

将您的声明更改为:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}

答案 2 :(得分:7)

实现接口的方式是显式实现void IDoesCoolThings.DoCool(),如果选择隐式实现接口。

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()
    {
        Console.Write("I did something cool.");
    }
}

然后它会起作用。

阅读本文:

C# Interfaces. Implicit implementation versus Explicit implementation

答案 3 :(得分:1)

你应该这样做:

public interface IDoesCoolThings 
{
   void DoCool();
}

public abstract class AbstractWidget 
{
   public void DoCool()
   {
      Console.WriteLine("I did something cool.");
   }
}

public class Widget : AbstractWidget, IDoesCoolThings 
{
}

用法:

var widget = new Widget();
widget.DoCool();