简体   繁体   English

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

[英]Using interfaces on abstract classes in C#

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. 我想解决方案很简单,但我尝试了各种各样的事情,因为我的生活无法想象这一点。

You're running into the issue because you used explicit interface implementation (EII). 您遇到了问题,因为您使用了显式接口实现 (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 . 在您的示例中,这就是为什么除非将实例IDoesCoolThingsIDoesCoolThings否则无法调用DoCool()

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 force clients 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.) (这被一些人认为是一种很好的做法。)

Change your declaration to: 将您的声明更改为:

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

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. C#接口。 Implicit implementation versus Explicit implementation 隐式实现与显式实现

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM