为什么我需要接口?

时间:2012-02-26 09:12:54

标签: c# .net inheritance interface

  

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

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

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

- Thx提前。

注意:我在.NET(C#)语言

的上下文中提出这个问题

Edit1 :现在每当我尝试学习界面时,我的思绪都会告诉我 - > “伙计你要用白纸勾勒出某人的身体”但是你需要另一张白纸,你必须再次画出轮廓,画出所有身体部位填充颜色给他们以获得真实的照片。所以我为什么要浪费第一张白纸只是为了得到轮廓。

2 个答案:

答案 0 :(得分:13)

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

数据库提供商:

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

IDbConnection connection = GetDatabaseConnectionFromConfig()
connection.Open()
// do stuff
connection.Close()

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

<强>类别:

如果您注意到几乎所有集合都实现了名为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
}

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

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

希望这有帮助。

答案 1 :(得分:6)

接口是一个契约,用于该类可以执行的操作,这意味着单个类可以实现多个合同。

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

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

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

如果您想预先指定部分功能然后添加到它上,您将使用抽象类。

编辑:请考虑一下:

您的应用程序需要存储一些数据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*/}
}
这里更好的方法是使用一个接口,该接口通常描述存储EntityA的内容。

例如

public interface IStoreEntityA{
    void Store(EnitityA entity);
}

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

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

这意味着您的逻辑与存储EntityA

的方式紧密相关