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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/684260/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 13:20:26  来源:igfitidea点击:

Using interfaces on abstract classes in C#

c#inheritanceinterfaceabstract-class

提问by JubJub

I'm learning C# coming from C++ and have run into a wall.

我正在学习来自 C++ 的 C#,但遇到了一堵墙。

I have an abstract class AbstractWidget, an interface IDoesCoolThings, and a class which derives from AbstractWidget called RealWidget:

我有一个抽象类 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
{

}

When I instantiate a RealWidget object and call DoCool() on it, the compiler gives me an error saying

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

'RealWidget' does not contain a definition for 'DoCool'

“RealWidget”不包含“DoCool”的定义

I can cast RealWidget object to an IDoesCoolThings and then the call will work, but that seems unnecessary and I also lose polymorphism (AbstractWidget.DoCool() will always be called even if i define RealWidget.DoCool()).

我可以将 RealWidget 对象转换为 IDoesCoolThings,然后调用将起作用,但这似乎没有必要,而且我也失去了多态性(即使我定义了 RealWidget.DoCool(),也将始终调用 AbstractWidget.DoCool())。

I imagine the solution is simple, but I've tried a variety of things and for the life of me can't figure this one out.

我想解决方案很简单,但我已经尝试了各种各样的事情,而且我一生都无法弄清楚这一点。

采纳答案by John Feminella

You're running into the issue because you used explicit interface implementation(EII). When a member is explicitly implemented, it can't be accessed through a class instance -- only through an instance of the interface. In your example, that's why you can't call DoCool()unless you cast your instance to IDoesCoolThings.

您遇到了这个问题,因为您使用了显式接口实现(EII)。当一个成员被显式实现时,它不能通过类实例访问——只能通过接口的实例。在您的示例中,这就是为什么DoCool()除非您将实例转换为IDoesCoolThings.

The solution is to make DoCool()public and remove the explicit interface implementation:

解决方案是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!

In general, you use EII in two cases:

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

  • You have a class that must implement two interfaces, each of which contains a member that has an identical name/signature to another member in the other interface.
  • You want to forceclients not to depend on the implementation details of your class, but rather on the interface that's being implemented by your class. (This is considered a good practice by some.)
  • 您有一个必须实现两个接口的类,每个接口都包含一个成员,该成员与另一个接口中的另一个成员具有相同的名称/签名。
  • 您希望强制客户端不依赖于您的类的实现细节,而是依赖于您的类正在实现的接口。(这被一些人认为是一种很好的做法。)

回答by Mitch Wheat

Change your declaration to:

将您的声明更改为:

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

回答by J.W.

The way you implement the interface is explicit implement void IDoesCoolThings.DoCool(), if you choose implicit implement interface.

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

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

Then it will work.

然后它会起作用。

Read this :

读这个 :

C# Interfaces. Implicit implementation versus Explicit implementation

C# 接口。隐式实现与显式实现

回答by Toffee

You should do it this way:

你应该这样做:

public interface IDoesCoolThings 
{
   void DoCool();
}

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

public class Widget : AbstractWidget, IDoesCoolThings 
{
}

Usage:

用法:

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