为什么我需要接口?

Pri*_*kar 6 .net c# inheritance interface

可能重复:
接口:为什么我似乎无法掌握它们?
我为什么要使用接口?

我认为这个问题重复了1000次,我很抱歉再次提问.我真的在寻找一个简单的简单答案,为什么我明确需要接口,或者如果你请解释一些我没有接口就无法实现的东西.

如果它是多重继承,那么我会请你给我一个简单的例子,通过它我可以理解为什么我需要接口.

- 提前.

注意:我在.NET(C#)语言的上下文中提出这个问题

编辑1:现在,每当我尝试学习界面时,我的思绪告诉我 - >"伙计你要用白纸勾勒出某人的身体"但是你还需要另一张白纸,你需要再次绘制轮廓,绘制所有身体部位填充颜​​色给他们以获得真实的图片".那么为什么我只是为了获得轮廓而浪费第一张白纸.

Des*_*tar 13

理解接口的最简单方法是允许不同的对象公开COMMON功能.这允许程序员编写更简单,更短的代码来编程到接口,然后只要对象实现该接口就可以工作.

数据库提供者:

有许多不同的数据库提供程序,MySQL,MSSQL,Oracle等.但是,所有数据库对象都可以执行相同的操作,因此您将找到许多数据库对象的接口.如果一个对象实现了IDBConnection,那么它会暴露方法Open()和Close().因此,如果我希望我的程序与数据库提供程序无关,我编程到接口而不是特定的提供程序.

IDbConnection connection = GetDatabaseConnectionFromConfig()
connection.Open()
// do stuff
connection.Close()
Run Code Online (Sandbox Code Playgroud)

通过编程到接口(IDbconnection),我现在可以在我的配置中SWAP出任何数据提供程序,但我的代码保持完全相同.这种灵活性非常有用且易于维护.这样做的缺点是我只能执行"通用"数据库操作,并且可能无法充分利用每个特定提供商提供的优势,因此在编程中您需要权衡一切,并且您必须确定哪种方案最有利于您.

类别:

如果您注意到几乎所有集合都实现了名为IEnumerable的接口.IEnumerable返回一个IEnumerator,它有MoveNext(),Current和Reset().这使C#可以轻松地在您的收藏中移动.它可以做到这一点的原因是因为它公开IEnumerable接口它知道对象公开它需要通过它的方法.这样做有两件事.1)foreach循环现在将知道如何枚举集合和2)您现在可以将强大的LINQ exprssions应用于您的集合.接口在这里非常有用的原因是因为所有集合在COMMON中都有一些东西,它们可以被移动.每个集合可以通过不同的方式(链表与数组)进行移动,但接口的优点在于实现是隐藏的,与接口的使用者无关.MoveNext()为您提供集合中的下一个项目,它如何做到并不重要.太好了,对吧?

多态性

当您设计自己的界面时,您只需要问自己一个问题.这些东西有什么共同之处?一旦找到对象共享的所有内容,就会将这些属性/方法抽象到接口中,以便每个对象都可以从中继承.然后,您可以使用一个界面对多个对象进行编程.

当然,我必须提供我最喜欢的C++多态示例,即动物示例.所有动物都具有某些特征.让我们说他们可以移动,说话,他们都有一个名字.因为我刚刚确定了我的所有动物的共同点,我可以将这些特质抽象到IAnimal界面中.然后我创建了一个Bear对象,一个Owl对象和一个Snake对象,它们都实现了这个接口.您可以将实现相同接口的不同对象存储在一起的原因是因为接口表示IS-A重放.熊IS-A动物,猫头鹰IS-A动物,因此我可以将它们全部收集为动物.

var animals = new IAnimal[] = {new Bear(), new Owl(), new Snake()} // here I can collect different objects in a single collection because they inherit from the same interface

foreach (IAnimal animal in animals) 
{
    Console.WriteLine(animal.Name)
    animal.Speak() // a bear growls, a owl hoots, and a snake hisses
    animal.Move() // bear runs, owl flys, snake slithers
}
Run Code Online (Sandbox Code Playgroud)

你可以看到,即使这些动物以不同的方式执行每个动作,我也可以在一个统一的模型中对它们进行编程,这只是Interfaces的众多好处之一.

因此,接口最重要的是对象的共同点,以便您可以以相同的方式对DIFFERENT对象进行编程.节省时间,创建更灵活的应用程序,隐藏复杂性/实施,模拟现实世界的对象/情况,以及许多其他好处.

希望这可以帮助.

  • 很好的答案. (2认同)

Not*_*ple 6

接口是类可以执行的合同,这意味着单个类可以实现多个合同.

抽象类是一个类应该如何表现的模板,每个类只能填写一个模板.

扩展类采用现有对象并添加/更改功能,每个类只能扩展一个父类.

如果要在不定义具体实现的情况下描述某些操作应该如何操作,则可以使用契约(接口).任何其他实现定义的方法/属性的类都可以实现此契约.

如果要预先指定部分功能然后添加到它上,则可以使用抽象类.

编辑:考虑一下:

您有一个应用程序需要存储一些数据Say EntityA但您可以有多种方式来存储数据(例如xml,SQL数据库,CSV等).您可以为这些不同的方法创建一个类来存储EntityA.但是当你想要改变方法时,你需要在那里明确指定你想要的类型.

public class DoStuffWithEntityA{
   public void DoStuffAndStoreAsXml(EntityA entity){ /*Logic*/}
   public void DoStuffAndStoreAsCsv(EntityA entity){ /*Logic*/}
   public void DoStuffAndStoreInDatabase(EntityA entity){ /*Logic*/}
}
Run Code Online (Sandbox Code Playgroud)

或许这里更好的方法是使用一个接口,它通常描述存储EntityA的东西是什么样的.

例如

public interface IStoreEntityA{
    void Store(EnitityA entity);
}
Run Code Online (Sandbox Code Playgroud)

然后你可以说你想要在你的代码中存储EntityA的东西

public class DoStuffWithEntityA{
    private IStoreEntityA _entityAStorer;
    public DoStuffWithEntityA(IStoreEntityA howIStoreEntityA){ _entityAStorer = howIStoreEntityA;}
    public void DoStuff(EntityA entity)
    {
        //Do Stuff
        _entityAStorer.Store(entity);
    }
}
Run Code Online (Sandbox Code Playgroud)

这意味着您的逻辑与存储EntityA的方式紧密相关