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

当前回答

以下是你的例子:

public interface IFood // not Pizza
{
    public void Prepare();

}

public class Pizza : IFood
{
    public void Prepare() // Not order for explanations sake
    {
        //Prepare Pizza
    }
}

public class Burger : IFood
{
    public void Prepare()
    {
        //Prepare Burger
    }
}

其他回答

接口用于驱动一致性,以一种松散耦合的方式,这使得它不同于紧密耦合的抽象类。这就是为什么它通常也被定义为合同。实现接口的任何类都必须遵守接口定义的“规则/语法”,并且其中没有具体的元素。

我将给出一个下图所支持的例子。

Imagine in a factory there are 3 types of machines.A rectangle machine,a triangle machine and a polygon machine.Times are competitive and you want to streamline operator training.You just want to train them in one methodology of starting and stopping machines so you have a green start button and red stop button.So now across 3 different machines you have a consistent way of starting and stopping 3 different types of machines.Now imagine these machines are classes and the classes need to have start and stop methods,how you going to drive consistency across these classes which can be very different? Interface is the answer.

一个简单的例子来帮助你可视化,有人可能会问为什么不用抽象类呢?有了接口,对象不必直接相关或继承,你仍然可以在不同的类之间保持一致性。

public interface IMachine
{
    bool Start();
    bool Stop();
}

public class Car : IMachine
{
    public bool Start()
    {
        Console.WriteLine("Car started");
        return true;
    }

    public bool Stop()
    {
        Console.WriteLine("Car stopped");
        return false;
    }
}

public class Tank : IMachine
{
    public bool Start()
    {
        Console.WriteLine("Tank started");
        return true;
    }

    public bool Stop()
    {
        Console.WriteLine("Tank stopped");
        return false;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var car = new Car();
        car.Start();
        car.Stop();

        var tank = new Tank();
        tank.Start();
        tank.Stop();

    }
}

考虑接口的最简单方法是认识继承的意义。如果类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.

上面的例子没有多大意义。你可以使用类来完成上面所有的例子(如果你想让它只表现为一个契约,那么它就是抽象类):

public abstract class Food {
    public abstract void Prepare();
}

public class Pizza : Food  {
    public override void Prepare() { /* Prepare pizza */ }
}

public class Burger : Food  {
    public override void Prepare() { /* Prepare Burger */ }
}

你会得到和界面相同的行为。您可以创建一个List<Food>,并迭代w/o知道什么类位于顶部。

更合适的例子是多重继承:

public abstract class MenuItem {
    public string Name { get; set; }
    public abstract void BringToTable();
}

// Notice Soda only inherits from MenuItem
public class Soda : MenuItem {
    public override void BringToTable() { /* Bring soda to table */ }
}


// All food needs to be cooked (real food) so we add this
// feature to all food menu items
public interface IFood {
    void Cook();
}

public class Pizza : MenuItem, IFood {
    public override void BringToTable() { /* Bring pizza to table */ }
    public void Cook() { /* Cook Pizza */ }
}

public class Burger : MenuItem, IFood {
    public override void BringToTable() { /* Bring burger to table */ }
    public void Cook() { /* Cook Burger */ }
}

然后你可以把它们都作为菜单项使用,而不用关心它们如何处理每个方法调用。

public class Waiter {
    public void TakeOrder(IEnumerable<MenuItem> order) 
    {
        // Cook first
        // (all except soda because soda is not IFood)
        foreach (var food in order.OfType<IFood>())
            food.Cook();

        // Bring them all to the table
        // (everything, including soda, pizza and burger because they're all menu items)
        foreach (var menuItem in order)
            menuItem.BringToTable();
    }
}

以下是你的例子:

public interface IFood // not Pizza
{
    public void Prepare();

}

public class Pizza : IFood
{
    public void Prepare() // Not order for explanations sake
    {
        //Prepare Pizza
    }
}

public class Burger : IFood
{
    public void Prepare()
    {
        //Prepare Burger
    }
}

下面是一个矩形对象的接口:

interface IRectangular
{
    Int32 Width();
    Int32 Height();
}

它所要求的是实现访问对象宽度和高度的方法。

现在让我们定义一个方法,它可以作用于任何irectangle对象:

static class Utils
{
    public static Int32 Area(IRectangular rect)
    {
        return rect.Width() * rect.Height();
    }
}

这将返回任意矩形物体的面积。

让我们实现一个矩形的类SwimmingPool:

class SwimmingPool : IRectangular
{
    int width;
    int height;

    public SwimmingPool(int w, int h)
    { width = w; height = h; }

    public int Width() { return width; }
    public int Height() { return height; }
}

另一个类House也是矩形的:

class House : IRectangular
{
    int width;
    int height;

    public House(int w, int h)
    { width = w; height = h; }

    public int Width() { return width; }
    public int Height() { return height; }
}

鉴于此,你可以在房屋或游泳池上调用Area方法:

var house = new House(2, 3);

var pool = new SwimmingPool(3, 4);

Console.WriteLine(Utils.Area(house));
Console.WriteLine(Utils.Area(pool));

通过这种方式,您的类可以从任意数量的接口“继承”行为(静态方法)。