Why I need Interface?
Possible Duplicate:
Interfaces: Why can't I seem to grasp them?
Why would I want to use Interfaces?
我想这个问题重复了1000次,很抱歉再问一次。我真的在寻找一个简单明了的答案,为什么我明确需要接口,或者如果你能解释一下没有接口我无法实现的东西。
如果它是多继承的,那么我将请求您给我一个简单的例子,通过这个例子我可以理解为什么我需要接口。
--THX提前。
注意:我是在.NET(C)语言的上下文中问这个问题的。
伊迪丝1:现在,每当我试图学习界面时,我的大脑告诉我:"伙计,你要用白纸勾勒出某人的身体轮廓",但你需要另一张白纸,在那里你必须再次画出轮廓,画出所有身体部位的填充颜色,才能得到真实的画面。"所以为什么我浪费第一张白纸只是为了得到轮廓。
理解接口最简单的方法是允许不同的对象公开公共功能。这样,程序员就可以编写更简单、更短的代码,将其编程到一个接口上,然后只要对象实现了该接口,它就可以工作。
数据库提供程序:
有许多不同的数据库提供程序,比如mysql、mssql、oracle等等,但是所有的数据库对象都可以做同样的事情,所以您可以找到许多数据库对象的接口。如果对象实现IDBConnection,则它将公开方法open()和close()。因此,如果我想让我的程序成为数据库提供者不可知论者,我就编程到接口,而不是特定的提供者。
1 2 3 4 | IDbConnection connection = GetDatabaseConnectionFromConfig() connection.Open() // do stuff connection.Close() |
通过编程到接口(idbConnection),我现在可以交换配置中的任何数据提供程序,但代码保持不变。这种灵活性非常有用,并且易于维护。这样做的缺点是,我只能执行"通用"数据库操作,并且可能无法充分利用每个特定提供者提供的优势,因此对于编程中的所有内容,您都有一个折衷方案,您必须确定哪种方案对您最有利。
收藏:
如果您注意到几乎所有的集合都实现了这个名为IEnumerable的接口。IEnumerable返回具有moveNext()、current和reset()的IEnumerator。这样C就可以轻松地浏览您的收藏。之所以可以这样做,是因为它公开了IEnumerable接口,它知道对象公开了它需要通过它的方法。这有两件事。1)foreach循环现在知道如何枚举集合,2)现在可以对集合应用强大的LINQ表达式。同样,接口在这里如此有用的原因是因为所有的集合都有共同点,所以可以移动它们。每个集合可以通过不同的方式移动(链表与数组),但接口的好处在于,实现是隐藏的,与接口的使用者无关。moveNext()为您提供集合中的下一个项,不管它是如何执行的。很好,嗯?
多态性
当你设计你自己的接口时,你只需要问你自己一个问题。这些东西有什么共同点?一旦找到对象共享的所有内容,就将这些属性/方法抽象到一个接口中,以便每个对象都可以从中继承。然后,您可以使用一个接口针对多个对象进行编程。
当然,我必须给我最喜欢的C++多态性例子,动物例子。所有动物都有某些特点。假设他们可以移动、说话,而且他们都有一个名字。因为我刚刚确定了我所有的动物都有什么共同点,我可以将这些特性抽象到iAnimal接口中。然后我创建了一个bear对象、一个owl对象和一个snake对象,所有这些都实现了这个接口。之所以可以将实现相同接口的不同对象存储在一起,是因为接口表示IS-A重放。熊是一种动物,猫头鹰是一种动物,所以我可以把它们作为动物收集起来。
1 2 3 4 5 6 7 8 | 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 } |
您可以看到,即使这些动物以不同的方式执行每个操作,我也可以在一个统一的模型中针对它们进行编程,这只是接口的诸多好处之一。
因此,对于接口来说,最重要的是对象有什么共同点,这样你就可以用同样的方法对不同的对象进行编程。节省时间、创建更灵活的应用程序、隐藏复杂性/实现、为现实对象/情况建模,以及许多其他好处。
希望这有帮助。
接口是类可以做什么的契约,这意味着一个类可以完成多个契约。
抽象类是一个类应该如何工作的模板,每个类只能填写一个模板。
扩展类接受现有对象并添加/更改功能,每个类只能扩展一个父类。
如果您想要描述在不定义特定实现的情况下应该如何操作,那么可以使用契约(接口)。这个契约可以通过实现定义的方法/属性的任何其他类来实现。
如果您想预先指定一部分功能,然后将其添加到抽象类中,那么可以使用抽象类。
编辑:考虑:
您有一个应用程序需要存储一些数据,比如EntityA,但您可能有多种存储数据的方法(例如XML、SQL数据库、CSV等)。您可以为这些不同的方法中的每一个创建一个类来存储EntityA。但是当您想要更改方法时,您需要显式地指定您想要的类型。
工业工程
1 2 3 4 5 | public class DoStuffWithEntityA{ public void DoStuffAndStoreAsXml(EntityA entity){ /*Logic*/} public void DoStuffAndStoreAsCsv(EntityA entity){ /*Logic*/} public void DoStuffAndStoreInDatabase(EntityA entity){ /*Logic*/} } |
prehaps这里一个更好的方法是使用一个接口,该接口通常描述存储entitya的内容的外观。
如
1 2 3 | public interface IStoreEntityA{ void Store(EnitityA entity); } |
然后你可以说你想要在你的代码中存储entitya的东西
1 2 3 4 5 6 7 8 9 | public class DoStuffWithEntityA{ private IStoreEntityA _entityAStorer; public DoStuffWithEntityA(IStoreEntityA howIStoreEntityA){ _entityAStorer = howIStoreEntityA;} public void DoStuff(EntityA entity) { //Do Stuff _entityAStorer.Store(entity); } } |
这意味着您的逻辑与存储实体的方式没有紧密耦合