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

当前回答

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

其他回答

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

考虑接口的最简单方法是认识继承的意义。如果类CC继承了类C,这意味着:

类CC可以使用类C的任何public或protected成员,就像它们是自己的一样,因此只需要实现父类中不存在的东西。 对CC的引用可以传递或分配给期望对C的引用的例程或变量。

遗传的这两个功能在某种意义上是相互独立的;虽然继承同时应用这两个,但也可以应用第二个而不应用第一个。这很有用,因为允许一个对象从两个或多个不相关的类继承成员要比允许一种类型可以替代多种类型复杂得多。

接口有点像抽象基类,但有一个关键的区别:继承基类的对象不能继承任何其他类。相反,一个对象可以实现一个接口,而不影响它继承任何所需类或实现任何其他接口的能力。

One nice feature of this (underutilized in the .net framework, IMHO) is that they make it possible to indicate declaratively the things an object can do. Some objects, for example, will want data-source object from which they can retrieve things by index (as is possible with a List), but they won't need to store anything there. Other routines will need a data-depository object where they can store things not by index (as with Collection.Add), but they won't need to read anything back. Some data types will allow access by index, but won't allow writing; others will allow writing, but won't allow access by index. Some, of course, will allow both.

If ReadableByIndex and Appendable were unrelated base classes, it would be impossible to define a type which could be passed both to things expecting a ReadableByIndex and things expecting an Appendable. One could try to mitigate this by having ReadableByIndex or Appendable derive from the other; the derived class would have to make available public members for both purposes, but warn that some public members might not actually work. Some of Microsoft's classes and interfaces do that, but that's rather icky. A cleaner approach is to have interfaces for the different purposes, and then have objects implement interfaces for the things they can actually do. If one had an interface IReadableByIndex and another interface IAppendable, classes which could do one or the other could implement the appropriate interfaces for the things they can do.

考虑到你不能在c#中使用多重继承,然后再看看你的问题。

什么?

接口基本上是一个契约,所有实现接口的类都应该遵循这个契约。它们看起来像一个类,但没有实现。

在c#中,接口名称的约定是由前缀“I”定义的,所以如果你想要一个名为shapes的接口,你可以将它声明为IShapes

为什么?

提高代码的可重用性

假设你想画圆,三角形。 你可以把它们组合在一起,称为形状,并有方法来绘制圆形和三角形 但有具体的实现将是一个坏主意,因为明天你可能会决定有2个形状矩形和正方形。现在,当您添加它们时,很可能会破坏代码的其他部分。

使用Interface,您可以将不同的实现与契约隔离开来


现场场景第一天

你被要求创建一个应用程序来绘制圆形和三角形

interface IShapes
{
   void DrawShape();
   
 }

class Circle : IShapes
{
    
    public void DrawShape()
    {
        Console.WriteLine("Implementation to Draw a Circle");
    }
}

Class Triangle: IShapes
{
     public void DrawShape()
    {
        Console.WriteLine("Implementation to draw a Triangle");
    }
}
static void Main()
{
     List <IShapes> shapes = new List<IShapes>();
        shapes.Add(new Circle());
        shapes.Add(new Triangle());

        foreach(var shape in shapes)
        {
            shape.DrawShape();
        }
}

现场场景第二天

如果你被要求添加Square和Rectangle,你所要做的就是在Square: IShapes类中创建它的实现,并在Main中添加到列表形状。添加(新广场());

我在这个页面上搜索了“合成”这个词,但一次也没看到。这个答案是对前面提到的答案的补充。

在面向对象项目中使用接口的一个绝对重要的原因是,它们允许你更倾向于组合而不是继承。通过实现接口,您可以将您的实现与应用于它们的各种算法解耦。

德里克·巴纳斯(Derek Banas)的“装饰图案”教程(有趣的是,它也以披萨为例)是一个有价值的插图:

https://www.youtube.com/watch?v=j40kRwSm4VE