接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合。一旦定义了接口,就可以在类中实现它。这样,类就可以支持接口所指定的所有属性和成员。接口不能单独存在;不能进行实例化(因为没有必要实例化);接口不包括任何实现其成员的代码而只定义了成员本身;成员的实现将在实现接口的类中实现。
以上是接口的书本定义,读完基本不知所云。就知道了接口与类不一样,接口与类都需要定义自身的成员,但接口不能实现成员的功能。我觉得可以简单地说:接口是类的更高级抽象(类已经是其所要实现的过程的抽象了),接口定义了类实现的规范。接口好像是事先定义好的备忘录,提醒你,类需要有这些成员,需要完成这些功能。但是,不同的类,他们具体的实现方式则需要你单独去定义了。
举一个简单的例子,我觉得很好很经典。
正如图中所示,我们定义了一个IHuman的接口,以及Student和Teacher两个类。众所周知,学生和老师都是人(虽然他们之间总是或多或少的存在着些许不可调和的矛盾)。因此,学生和老师都有年龄的属性、同样需要吃饭、睡觉...。
但是,几乎可以确定的是,学生和老师是两代人,他们之间有代沟,去完成作为一个人所必须完成的事情的时候,所采用的方式方法是不同的。同时,他们也有不同的行为。比如,一个30岁的副教授,想必已经结婚,所以需要传宗接代、孝敬父母、爱护祖国花朵、教书育人、赚钱糊口...。而学生呢,正值妙龄,血气方刚,不甘寂寞,可想而知...
这样做有什么好处呢?毕竟,没有好处的事情是不会有人去做的。试想,我们没有定义IHuman接口,而是分别定义了Student、Teacher类。有一天,一个想儿子想疯了的家长突然出现在不知所措的学生和老师中间。你需要重新定义一个Parent类,他既不去食堂吃饭也不回家睡觉,一切食宿都在宾馆解决。万一你忘记了Parent也是正常人,没有定义Parent如何去睡觉,是不是要让Parent活活困死呢?当有一天,全国千千万万的新新人类都来到了校园,你会忘记的事情是不是也将会是千千万万,你害死的鲜活生命何以计数呢?
当我们有了IHuman接口,不管怎么说,家长还是人,我们定义一个parent类:
家长此行的其他目的,无非是对学生晓之以钱,对老师动之以礼等等,可以随他折腾了。同时,你还没有忘记需要完美地解决家长的食宿问题。所有的新新人类还是人,完全不用担心你会忘记他们作为人的需求(忘记了?会有编译错误报告告诉你的...)。
上面只是举了一个接口与多个类的例子。实际应用中,我们可以再定义一个ITeacher的接口,Teacher类对应IHuman和ITeacher两个接口,分别规范了老师作为一名人民教师以及一个人的动作。也就是一个类可以同时实现多个接口。
不过好像还是不太明白接口与基类的区别。以下是几个形象的比喻:
1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;然而同样会飞的F22和鸽子,一个属于“飞机”类,另一个属于“鸟”类。
2. 铁门跟木门都是门(基类),你想要个门我给不了(基类不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(继承类只能继承于一个基类——单继承);一个门可以有锁(接口)也可以有门铃(另一个接口,多实现)。 门定义了你是什么,接口(锁、门铃)规定了你能做什么,(一个接口最好只能做一件事,你不能要求锁也能发出声音吧)。至于铁门的锁是什么牌子的,木门的门铃是什么声音的,那就是铁门和木门需要关心的事儿了。总结
以下是我们必须牢记于心的地方,接口只包含方法、委托或事件的签名。方法的实现是在实现接口的类中完成的,接口可以是命名空间或类的成员,并且可以包含下列成员的签名:方法、属性、索引器、事件,一个接口可从一个或多个基接口继承。当基类型列表包含基类和接口时,基类必须是列表中的第一项。实现接口的类可以显式实现该接口的成员。显式实现的成员不能通过类实例访问,而只能通过接口实例访问。
通常认为接口要比基类更加灵活,类只要实现了某一接口,调用者便可以利用该接口实现多态访问,在组件化开发中很常用,由组件规范定义者去定义一个接口,不同分工的发人员按照各自的目的去实现这个接口。而基类的方式相对比较死板,但有一些比较通用的方法就可以不必在子类中重写了。二者不能够说谁的功能更强大,或者说谁能取代谁,只是我们可以根据需要选用。例如.net框架中的TextBox,Label等是从WebControl继承过来,采用基类的方式,而SqlConnection和OracleConnection实现IDbConnection的接口,这样程序就可以使用IDbConnection接口去访问不同类型的数据库。