我真的不明白接口存在的原因。据我所知,这是c#中不存在的多继承的一种工作(至少我是这么被告知的)。

我所看到的是,您预定义了一些成员和函数,然后必须在类中再次重新定义它们。从而使接口成为冗余。它只是感觉像句法……嗯,垃圾对我来说(请没有冒犯的意思。Junk是指无用的东西)。

在下面的例子中,我将创建一个名为Pizza的基类,而不是一个接口。

简单示例(取自不同的堆栈溢出贡献)

public interface IPizza
{
    public void Order();
}

public class PepperoniPizza : IPizza
{
    public void Order()
    {
        //Order Pepperoni pizza
    }
}

public class HawaiiPizza : IPizza
{
    public void Order()
    {
        //Order HawaiiPizza
    }
}

当前回答

class Program {
    static void Main(string[] args) {
        IMachine machine = new Machine();
        machine.Run();
        Console.ReadKey();
    }

}

class Machine : IMachine {
    private void Run() {
        Console.WriteLine("Running...");
    }
    void IMachine.Run() => Run();
}

interface IMachine
{
    void Run();
}

让我从另一个角度来描述一下。让我们根据上面的例子来创建一个故事;

程序、机器和IMachine是我们故事的演员。程序想要运行,但它没有这个能力,而机器知道如何运行。机器和IMachine是最好的朋友,但程序和机器没有说话的关系。于是程序和IMachine做了一个交易,决定IMachine通过观察机器(就像一个反射器)来告诉程序如何运行。

Program在IMachine的帮助下学习如何运行。

接口提供通信和开发松散耦合的项目。

PS:我把具体类的方法作为私有。我在这里的目标是通过防止访问具体的类属性和方法来实现松耦合,只允许通过接口访问它们。(所以我明确地定义了接口的方法)。

其他回答

考虑一下不控制或不拥有基类的情况。

以可视化控件为例,在。net for Winforms中,它们都继承自。net框架中完全定义的基类Control。

让我们假设您从事创建自定义控件的业务。你想要建立新的按钮,文本框,列表视图,网格,等等,你希望他们都有特定的功能独特的控件集。

例如,你可能想要一种通用的方法来处理主题,或者一种通用的方法来处理本地化。

在这种情况下,你不能“只创建一个基类”,因为如果你这样做,你必须重新实现所有与控件相关的东西。

相反,您将从按钮,TextBox, ListView, GridView等下降,并添加您的代码。

但这就产生了一个问题,你现在如何识别哪些控件是“你的”,你如何构建一些代码来表明“对于窗体上所有属于我的控件,将主题设置为X”。

输入接口。

接口是一种查看对象、确定对象是否遵守某种约定的方法。

您可以创建“YourButton”,从Button向下延伸,并添加对所需的所有接口的支持。

这将允许您编写如下代码:

foreach (Control ctrl in Controls)
{
    if (ctrl is IMyThemableControl)
        ((IMyThemableControl)ctrl).SetTheme(newTheme);
}

如果没有接口,这是不可能的,相反,你必须写这样的代码:

foreach (Control ctrl in Controls)
{
    if (ctrl is MyThemableButton)
        ((MyThemableButton)ctrl).SetTheme(newTheme);
    else if (ctrl is MyThemableTextBox)
        ((MyThemableTextBox)ctrl).SetTheme(newTheme);
    else if (ctrl is MyThemableGridView)
        ((MyThemableGridView)ctrl).SetTheme(newTheme);
    else ....
}

我知道我已经迟到了。(差不多九年了),但如果有人想要简单的解释,你可以这样说:

简单地说,当你知道一个对象可以做什么,或者我们要在一个对象上实现什么函数时,你就使用接口。使用实例插入、更新和删除。

interface ICRUD{
      void InsertData(); // will insert data
      void UpdateData(); // will update data
      void DeleteData(); // will delete data
}

重要提示:接口总是公共的。

希望这能有所帮助。

I share your sense that Interfaces are not necessary. Here is a quote from Cwalina pg 80 Framework Design Guidelines "I often here people saying that interfaces specify contracts. I believe this a dangerous myth. Interfaces by themselves do not specify much. ..." He and co-author Abrams managed 3 releases of .Net for Microsoft. He goes on to say that the 'contract' is "expressed" in an implementation of the class. IMHO watching this for decades, there were many people warning Microsoft that taking the engineering paradigm to the max in OLE/COM might seem good but its usefulness is more directly to hardware. Especially in a big way in the 80s and 90s getting interoperating standards codified. In our TCP/IP Internet world there is little appreciation of the hardware and software gymnastics we would jump through to get solutions 'wired up' between and among mainframes, minicomputers, and microprocessors of which PCs were just a small minority. So coding to interfaces and their protocols made computing work. And interfaces ruled. But what does solving making X.25 work with your application have in common with posting recipes for the holidays? I have been coding C++ and C# for many years and I never created one once.

class Program {
    static void Main(string[] args) {
        IMachine machine = new Machine();
        machine.Run();
        Console.ReadKey();
    }

}

class Machine : IMachine {
    private void Run() {
        Console.WriteLine("Running...");
    }
    void IMachine.Run() => Run();
}

interface IMachine
{
    void Run();
}

让我从另一个角度来描述一下。让我们根据上面的例子来创建一个故事;

程序、机器和IMachine是我们故事的演员。程序想要运行,但它没有这个能力,而机器知道如何运行。机器和IMachine是最好的朋友,但程序和机器没有说话的关系。于是程序和IMachine做了一个交易,决定IMachine通过观察机器(就像一个反射器)来告诉程序如何运行。

Program在IMachine的帮助下学习如何运行。

接口提供通信和开发松散耦合的项目。

PS:我把具体类的方法作为私有。我在这里的目标是通过防止访问具体的类属性和方法来实现松耦合,只允许通过接口访问它们。(所以我明确地定义了接口的方法)。

在这种情况下,您可以(也可能会)定义一个Pizza基类并从它们继承。然而,接口允许你做一些其他方式无法做到的事情有两个原因:

一个类可以实现多个接口。它只是定义类必须具有的特性。实现一系列接口意味着一个类可以在不同的地方实现多种功能。 接口可以定义在比类或调用方更大的范围内。这意味着您可以分离功能,分离项目依赖项,并将功能保留在一个项目或类中,并在其他地方实现该功能。

2的一个含义是,您可以更改正在使用的类,只需要它实现适当的接口。