【问题标题】:C# interface instance-like... help me understand [duplicate]C# interface instance-like ...帮助我理解[重复]
【发布时间】:2012-08-03 09:53:13
【问题描述】:

可能重复:
Interfaces: Why can't I seem to grasp them?

要使用我刚刚发现的库,我需要先实现一些接口。但是有些方法似乎要求具有某些接口类型的对象...... 如果我有一个名为 MyInterface 的接口,我可以编写如下内容:

    MyInterface shoe;

这对我来说真的没有意义。有人可以教我这个概念吗? 我读到这个:http://www.dotnetperls.com/interface 但它并没有真正帮助,我认为这个概念比这里介绍的要复杂一些。

谢谢!

编辑:

对于那些想知道的人,我对接口并不陌生,但这是我第一次遇到这样的使用它们。对于那些将我的问题降级的人,我确实进行了搜索,但显然很不走运。

【问题讨论】:

标签: c# interface instance


【解决方案1】:

简单的解释:一个班级就像一个公司。如果它声称是销售公司,它必须提供销售服务。它自称是火车工厂,它必须能够制造火车。 国铁要买火车,只要能生产火车的公司都可以。

接口描述了一个类必须能够做什么。这就像一份合同。每个想要拥有接口的类都必须履行该合同并能够执行合同规定的事情。类实例可以通过类方法执行动作。

但是,合同并没有说明如何类应该这样做。所以一个类可以实现它想要的功能,或者换句话说,实现接口

public Train
{
    private price;
    public Train(float price) { this.price = price; }
}

public IMyInterface
{
   Train MakeTrain();
}

public ExpensiveTrainFactory : ITrainProducer
{
    // make a luxury, expensive train
    public Train MakeTrain() { return new Train(4000.0); }
}

public CheapTrainFactory : ITrainProducer
{
    // make a cheap train
    public Train MakeTrain() { return new Train(500.0); }
}

public NationalRailways
{
    List<Train> trains;
    public NationalRailways()
    {
        this.trains = new List<Train>();
    }
    public Train BuyTrain(ITrainProducer factory)
    {
        // you can call MakeTrain() because the ITrainProducer guarantees that it can make trains
        trains.Add(factory.MakeTrain());
    }
}

然后在你的代码中:

NationalRailways railway = new NationalRailways();
ExpensiveTrainFactory expFactory = new ExpensiveTrainFactory();
CheapTrainFactory cheapFactory = new CheapTrainFactory();

// expFactory implements ITrainProducer, so I can use it from BuyTrain(ITrainProducer)
railways.BuyTrain(expFactory);
// cheapFactory implements ITrainProducer, so I can use it from BuyTrain(ITrainProducer)  as well
railways.BuyTrain(cheapFactory);

【讨论】:

  • 嗯...这不是我的问题,我知道接口是什么,我对软件开发并不陌生...但无论如何谢谢
  • @Lewis 那么我一定误解了你的问题。您愿意编辑您的问题以使其更清晰吗?
  • @Lewis 您可能以前见过接口,但是阅读您的 cmets 和编辑后,您似乎还没有意识到您可以对接口进行编程。通过接口编程到接口和多态的概念确实使接口作为一个概念有用。请注意,BuyTrain 期望您所谓的“接口实例”——它实际上期望任何实现 ITrainProducer 接口的类。另请注意,MakeTrain 为实现 ITrainProducer 接口的不同类生成不同的火车 - 便宜或昂贵。
  • 是的,我明白你在说什么。问题是我倾向于使用更多的抽象类,因为大多数时候我觉得不需要接口。在我尝试使用的库中,我理解为什么要使用它:因为您不能使用可能不适合您的类模型逻辑的类创建继承,更重要的是对于那些还不存在并且可能完全不同但会仍然使用某些功能...在您的界面中声明。
  • @Lewis 同样重要的是要注意structs 也可以实现接口,与类继承不同,一个类(或结构)可以实现(继承)多个接口。
【解决方案2】:

您可以声明一个接口,就像在您的示例中一样。但是你不能实例化一个。

MyInterface shoe = new MyInterface ();

以上不是合法代码。由于接口只是描述一个合约,它没有实现细节,这留给客户端代码(你)。因此,能够创建 MyInterface 的实际实例是没有意义的。

你能做的,是有一个类 SomeClass,实现 MyInterface 契约:

SomeClass: MyInterface
{
  //implement the methods of MyInterface. All of them, to fulfill the contract.
}

然后您可以执行以下操作:

MyInterface shoe = new SomeClass();

由于 SomeClass 实现了 MyInterface 契约,所以上面是合法的。您可以创建 SomeClass 的实例,因为它包含实现细节。

然后您可以在此基础上构建并创建更多实现 MyInterface 的类。

这样做的好处是你可以有一个方法,例如:

void someMethod (MyInterface test)
{

}

您可以将此方法传递给 SomeClass 对象或您创建的任何其他实现 MyInterface 的类。

然后在这个方法中,你可以在不知道传递给你的确切对象的情况下调用合约包含的方法。这使得编写未来的代码更容易。您可以创建新对象,只要它们实现了 MyInterface,在不更改方法声明的情况下将此对象传递给 someMethod 是有效的。

【讨论】:

  • 谢谢!这很清楚。这个概念与抽象类概念平行。
【解决方案3】:

你是对的,你不能直接创建一个接口的实例。但是,您可以创建一个实现该接口的某种类型的实例。

假设我有一个接口

public IMyInterface
{
   void DoSomething();
}

(注意:接口名称通常以“I”开头)

另外我还有一门课

public MyClass: IMyInterface
{
    public void DoSomething() { ... }
}

那我就可以了

IMyInterface something = new MyClass();

虽然你经常调用一些(工厂)方法来返回一些实现该接口的类,而不是直接执行new

通过使用接口作为变量的类型,您可以指定您只对那里指定的方法和属性感兴趣。

【讨论】:

  • 我现在理解得更好了……但尽管我看不出有任何用处。谢谢 =)
  • @Lewis 有一个非常强大的用途,称为多态性:您可以拥有一组不同的对象(例如数据源),它们具有共同的接口,但实现方式不同(例如平面文件、XML 文件和数据库) - 然后您可以随意混合、匹配和修改它们,而无需修改使用此类对象的类。
  • @Lewis - 该库接受该接口类型的参数:这意味着接受任何类,即使是您编写的类,只要它们实现该接口
  • @llmo Euro:感谢您的澄清!只是我倾向于使用更多的抽象类来实现多态性......除非我需要解决继承逻辑,否则我觉得不需要接口。
  • @Hanks Kesting:谢谢,你们中的许多人都提到了它
【解决方案4】:

在 C# 中,每个值都有两种不同的类型:apparent 类型和 actual 类型。表观类型是保存该值的变量的类型,而实际类型来自用于创建该值的构造函数。假设我们有以下类:

class MyClass : BaseClass, IMyInterface {
    /* ... */
}

那么以下所有声明都是有效的:

object obj1 = new MyClass();
IMyInterface obj2 = new MyClass();
BaseClass obj3 = new MyClass();
MyClass obj4 = new MyClass();

表观类型和实际类型如下:

object obj1 = new MyClass(); /* apparent: object, actual: MyClass */
IMyInterface obj2 = new MyClass(); /* apparent: IMyInterface, actual: MyClass */
BaseClass obj3 = new MyClass(); /* apparent: BaseClass, actual: MyClass */
MyClass obj4 = new MyClass(); /* apparent: MyClass, actual: MyClass */

当你操作一个对象(调用它的方法等)时,你会假设对象有它的明显类型——你不能调用object的任何特定于类的方法。表观类型决定了在对象外部可见的对象的接口

实际上发生的事情是根据对象的实际类型来完成的——例如,如果你覆盖了你的类的ToString方法,那么被覆盖的方法会在下面的代码中被调用:

object obj = new MyClass();
Console.WriteLine(obj.ToString());

实际类型决定了对象的功能如何实现

【讨论】:

  • 啊很有趣!!谢谢
【解决方案5】:

接口在类和调用它的代码之间建立契约。它们还允许您拥有实现相同接口但执行不同操作或事件的类似类,而不必知道您实际使用的是哪个类。作为一个例子,这可能更有意义,所以让我使用与您的链接相同的示例,并进行一些修改:

using System;

interface IPerl
{
    void Read();
}

class Test : IPerl
{
    public void Read()
    {
    Console.WriteLine("Read Test");
    }
}

class Test1 : IPerl
{
    public void Read()
    {
    Console.WriteLine("Read Test1");
    }
}

class Program
{
    static void Main()
    {
    IPerl perl = new Test(); // Create instance of Test.
    perl.Read(); // Call method on interface output will be different then Test1.

        perl = new Test1(); // Create instance of Test1.
    perl.Read(); // Call method on interface output will be different then Test.

    }
}

输出:

  1. “读取测试”
  2. “读取测试1”

我希望这会有所帮助。

感谢安库

【讨论】:

    【解决方案6】:

    什么是接口

    接口基本上定义了类或结构的蓝图。接口的编程定义看起来非常类似于类,但没有实现任何内容。接口定义属性、方法、事件和索引器,但接口不定义任何这些的实现。它只是宣布它们的存在。接口实际上不会定义任何功能。它们只是定义了与类进行交互的方式。

    哪些接口不是

    接口不应与继承相混淆。它们是两个非常不同的东西。继承会定义很多实现,并用于代码重用。接口只是对必须如何与实现类进行通信的定义。这就像一份书面合同。 “签署”合同的类将同意以它希望的任何方式执行某些指定的操作,但它必须执行指定的操作。

    何时使用接口

    接口允许我们为类将要实现的内容创建漂亮的布局。由于接口给我们的保证,当许多组件使用相同的接口时,它允许我们轻松地将一个组件与另一个使用相同接口的组件互换。动态程序由此开始很容易形成。

    有关更多信息,请访问有关Understanding_Interfaces_in_C#的帖子

    【讨论】:

    • site guidelines strongly discourage 仅发布链接而不描述其内容的最重要部分。
    • @O.R.Mapper 对此我很抱歉。我现在更新了我的帖子。感谢您告知我这件事。
    • 我对接口已经很熟悉了,只是奇怪地没有遇到这种用法。如果我的问题不清楚,我很抱歉。
    猜你喜欢
    • 2020-12-29
    • 1970-01-01
    • 2010-11-12
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多