我知道他们强迫你实现方法等,但我不明白为什么你想要使用它们.任何人都可以给我一个很好的例子或解释我为什么要实现这个.
一个具体的例子:接口是指定其他人的代码必须满足的合同的好方法.
如果我正在编写代码库,我可能会编写对具有某组行为的对象有效的代码.最好的解决方案是在接口中指定这些行为(无实现,只是描述),然后在我的库代码中使用对实现该接口的对象的引用.
然后任何随机的人都可以来,创建一个实现该接口的类,实例化该类的对象并将其传递给我的库代码并期望它工作.注意:当然可以严格实现接口而忽略接口的意图,因此仅仅实现接口并不能保证事情能够正常工作.愚蠢总能找到方法!:-)
另一个具体的例子:两个团队致力于必须合作的不同组件.如果两个团队在第1天坐下并同意一组接口,那么他们可以分别采用各种方式并围绕这些接口实现其组件.团队A可以构建测试工具,模拟团队B中的组件进行测试,反之亦然.并行开发,减少错误.
关键点在于接口提供了一个抽象层,以便您可以编写不了解不必要细节的代码.
大多数教科书中使用的规范示例是排序例程.只要您有比较任何两个对象的方法,就可以对任何类对象进行排序.因此,您可以通过实现IComparable
接口来使任何类可排序,这会强制您实现比较两个实例的方法.编写所有排序例程以处理对IComparable对象的引用,因此只要实现IComparable,就可以在类的对象集合中使用任何这些排序例程.
接口定义合同,这是关键词.
当您需要在程序中定义合同时使用接口,但是您并不真正关心满足该合同的类的其余属性,只要它确实如此.
那么,让我们看一个例子.假设您有一个方法,它提供了对列表进行排序的功能.第一件事......什么是清单?你真的关心它为了对列表进行排序所拥有的元素吗?您的答案应该是否定的......在.NET(例如)中,您有一个名为IList的接口,它定义了列表必须支持的操作,因此您不关心表面下的实际细节.
回到这个例子,你真的不知道列表中对象的类......你也不在乎.如果您可以只是比较对象,也可以对它们进行排序.所以你申报合同:
interface IComparable { // Return -1 if this is less than CompareWith // Return 0 if object are equal // Return 1 if CompareWith is less than this int Compare(object CompareWith); }
该合同指定必须实现接受对象并返回int的方法才能进行比较.现在你已经定义了一个合同,现在你不关心对象本身,而是关心合同,所以你可以这样做:
IComparable comp1 = list.GetItem(i) as IComparable; if (comp1.Compare(list.GetItem(i+1)) < 0) swapItem(list,i, i+1)
PS:我知道这些例子有点幼稚,但它们就是例子......
一个典型的例子是插件架构.开发人员A编写主应用程序,并希望确保开发人员B,C和D编写的所有插件符合他的应用程序对他们的期望.
理解接口的最简单方法是允许不同的对象公开COMMON功能.这允许程序员编写更简单,更短的代码来编程到接口,然后只要对象实现该接口就可以工作.
示例1: 有许多不同的数据库提供程序,MySQL,MSSQL,Oracle等.但是,所有数据库对象都可以执行相同的操作,因此您可以找到许多数据库对象的接口.如果一个对象实现了IDBConnection,那么它会暴露方法Open()和Close().因此,如果我希望我的程序与数据库提供程序无关,我编程到接口而不是特定的提供程序.
IDbConnection connection = GetDatabaseConnectionFromConfig() connection.Open() // do stuff connection.Close()
通过编程到接口(IDbconnection),我现在可以在我的配置中SWAP出任何数据提供程序,但我的代码保持完全相同.这种灵活性非常有用且易于维护.这样做的缺点是我只能执行"通用"数据库操作,并且可能无法充分利用每个特定提供商提供的优势,因此在编程中您需要权衡一切,并且您必须确定哪种方案最有利于您.
示例2: 如果您注意到几乎所有集合都实现了名为IEnumerable的接口.IEnumerable返回一个IEnumerator,它有MoveNext(),Current和Reset().这使C#可以轻松地在您的收藏中移动.它可以做到这一点的原因是因为它公开IEnumerable接口它知道对象公开它需要通过它的方法.这样做有两件事.1)foreach循环现在将知道如何枚举集合和2)您现在可以将强大的LINQ exprssions应用于您的集合.接口在这里非常有用的原因是因为所有集合在COMMON中都有一些东西,它们可以被移动.每个集合可以通过不同的方式(链表与数组)进行移动,但接口的优点在于实现是隐藏的,与接口的使用者无关.MoveNext()为您提供集合中的下一个项目,它如何做到并不重要.太好了,对吧?
示例3: 当您设计自己的界面时,您只需要问自己一个问题.这些东西有什么共同之处?一旦找到对象共享的所有内容,就会将这些属性/方法抽象到接口中,以便每个对象都可以从中继承.然后,您可以使用一个界面对多个对象进行编程.
当然,我必须提供我最喜欢的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对象进行编程.节省时间,创建更灵活的应用程序,隐藏复杂性/实施,模拟现实世界的对象/情况,以及许多其他好处.
希望这可以帮助.
汽车上的踏板实现接口。我来自美国,我们在马路右侧行驶。我们的方向盘在汽车的左侧。从左到右的手动变速踏板为离合器->制动器->油门。当我去爱尔兰时,驾驶方向相反。汽车的方向盘在右侧,并且在道路的左侧行驶...但是踏板,踏板啊,它们实现了相同的界面,所有三个踏板的顺序都相同...因此,即使班级不同并且班级所使用的网络也不相同,我仍然对踏板接口感到满意。就像其他每辆车一样,我的大脑也能够在这辆车上呼唤我的肌肉。
想一想我们离不开的众多非编程接口。然后回答您自己的问题。