我真的不明白接口存在的原因。据我所知,这是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
    }
}

当前回答

这么多答案! 尽我所能。呵呵。

首先,你可以使用一个具体的基类和派生类。在这种情况下,你将不得不在基类中为Prepare方法做一个空的或无用的实现,同时使这个方法为虚的,然后派生类将为自己重写这个Prepare方法。在这种情况下,在基类中实现Prepare是无用的。

选择使用接口的原因是必须定义契约,而不是实现。

有一个IPizza类型,它提供了一个功能来准备。这是合同。它是如何准备的是实现,这不是你的把关。这是各种Pizza实现的责任。 这里首选接口或抽象类而不是具体基类,因为您必须创建一个抽象,即Prepare方法。不能在具体基类中创建抽象方法。

现在你可能会说,为什么不用抽象类呢?

所以,当你需要实现100%的抽象时,你需要使用接口。但是当你需要一些抽象和具体的实现时,选择抽象类。它的意思。

例子:假设你所有的披萨都有底料,底料的准备过程是相同的。然而,所有披萨的种类和配料都有所不同。在这种情况下,您可以使用一个抽象方法Prepare和一个具体方法PreparePizzaBase创建一个抽象类。

public abstract class Pizza{
    // concrete method which is common to all pizzas.
    public PizzaBase PreparePizzaBase(){
        // code for pizza base preparation.
    }
    public abstract void Prepare();
}

public class DeluxePizza: Pizza{
    public void Prepare(){
        var base=PreparePizzaBase();
        // prepare deluxe pizza on pizza base.
    }
}

其他回答

Interface =契约,用于松耦合(参见GRASP)。

如果我正在使用一个API来绘制形状,我可能想使用DirectX或图形调用,或OpenGL。因此,我将创建一个接口,它将从您调用的内容中抽象出我的实现。

所以你调用一个工厂方法:MyInterface i = MyGraphics.getInstance()。然后,你有一个契约,所以你知道你可以在MyInterface中期望什么功能。你可以调用i。drawrectangle或i。drawcube并且知道如果你把一个库换成另一个库,函数是被支持的。

如果您正在使用依赖注入,这就变得更加重要,因为您可以在XML文件中交换实现。

所以,你可能有一个加密库可以导出,供一般使用,而另一个加密库只出售给美国公司,区别在于你改变了配置文件,而程序的其余部分不会改变。

这在。net中的集合中被大量使用,就像你应该只使用,例如,列表变量,不要担心它是一个数组列表还是LinkedList。

只要您编写了接口代码,那么开发人员就可以更改实际的实现,而程序的其余部分则保持不变。

这在单元测试时也很有用,因为您可以模拟出整个接口,因此,我不需要访问数据库,而是只返回静态数据的模拟出来的实现,因此我可以测试我的方法,而不用担心数据库是否需要维护。

我很惊讶,没有多少文章包含一个最重要的接口原因:设计模式。这是使用契约的更大的前景,尽管它是机器代码的语法装饰(老实说,编译器可能会忽略它们),但抽象和接口对于OOP、人类理解和复杂的系统架构来说是至关重要的。

让我们把披萨的比喻扩大到一顿完整的大餐。对于所有的食物类别,我们仍然有核心的Prepare()接口,但我们也有针对课程选择(前菜、主菜、甜点)的抽象声明,以及针对食物类型(咸的/甜的、素食的/非素食的、无麸质的等)的不同属性。

基于这些规范,我们可以实现抽象工厂模式来概念化整个过程,但是使用接口来确保只有基础是具体的。其他一切都可以变得灵活或鼓励多态,同时在实现iccourse接口的不同Course类之间保持封装。

如果我有更多的时间,我想画一个完整的例子,或者有人可以为我扩展它,但总的来说,c#接口将是设计这类系统的最佳工具。

在Python中没有鸭子类型的情况下,c#依赖接口来提供抽象。如果类的依赖项都是具体类型,则不能传入任何其他使用类型的接口,可以传入实现该接口的任何类型。

这些都是很好的例子。

另外,在switch语句的情况下,您不再需要在每次希望里约热内卢以特定方式执行任务时进行维护和切换。

在你的披萨例子中,如果你想做一个披萨,界面就是你所需要的,从那里每个披萨都有自己的逻辑。

这有助于减少耦合和圈复杂度。您仍然需要实现逻辑,但在更广泛的情况下,您需要跟踪的内容将更少。

对于每个披萨,您可以跟踪特定于该披萨的信息。其他披萨有什么并不重要,因为只有其他披萨需要知道。