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

发布于 2024-07-15 06:05:54 字数 721 浏览 6 评论 0原文

我正在从 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() 也将始终被调用)。

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

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

I have an abstract class AbstractWidget, an interface IDoesCoolThings, and a class which derives from AbstractWidget called 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' does not contain a
definition for '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()).

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

初与友歌 2024-07-22 06:05:54

您遇到此问题是因为您使用了 < em>显式接口实现 (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:

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

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.

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

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:

  • 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.)
无言温柔 2024-07-22 06:05:54

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

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

然后它就会起作用。

阅读此内容:

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

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

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

盗心人 2024-07-22 06:05:54

将您的声明更改为:

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

Change your declaration to:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}
壹場煙雨 2024-07-22 06:05:54

你应该这样做:

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

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文