C# 在C中使用抽象类上的接口# 我正在学习C++的C语言,并已经进入了一个墙。< /P>

C# 在C中使用抽象类上的接口# 我正在学习C++的C语言,并已经进入了一个墙。< /P>,c#,inheritance,interface,abstract-class,C#,Inheritance,Interface,Abstract Class,我有一个抽象类AbstractWidget、一个接口IDoeSoolThings和一个从AbstractWidget派生的类RealWidget: public interface IDoesCoolThings { void DoCool(); } public abstract class AbstractWidget : IDoesCoolThings { void IDoesCoolThings.DoCool() { Console.Write(

我有一个抽象类AbstractWidget、一个接口IDoeSoolThings和一个从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对象强制转换为IDoeSoolThings,然后调用就可以了,但这似乎是不必要的,而且我还失去了多态性(AbstractWidget.DoCool()将始终被调用,即使我定义了RealWidget.DoCool()


我想解决方法很简单,但我尝试了很多方法,但我一辈子都无法解决这个问题。

你遇到这个问题是因为你使用了(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:

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

将您的声明更改为:

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

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

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

请阅读以下内容:


你应该这样做:

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();

要在小部件的DoCool()中具有多态性,需要声明AbstractWidget的一个virtual.Erg。我曾在某个地方读到虚拟是接口方法的暗示。天哪,我想我已经试过了。谢谢在我的参考书中,我似乎错过了这句关键的话:“通过使用显式接口实现定义的方法不能声明为虚拟,而省略接口名称允许这种行为。”我很困惑,仅仅在抽象类中公开方法并不能解决问题,另外,我阅读的示例没有将方法定义为public或private,因此我开始相信接口方法是隐式的public和virtual。总的来说,这是一个令人尴尬的问题:)。谢谢你!如果派生类对成员的重写可能希望返回从基类实现派生的类型,则显式接口实现也可能是好的。例如,
CarFactory
ICarFactory
可能都有
MakeCar()
方法返回
Car
,但
FordCarFactory
可能希望有
MakeCar()
方法返回
FordCar
。这通常可以通过使用一个返回
Car
protected
virtual
DoMakeCar
方法,并同时使用
ICarFactory.MakeCar
和一个非virtual
CarFactory.MakeCar
方法链来最好地处理。感谢您添加了关于隐式和显式实现的SO问题的链接!