我想, 对于各位使用面向对象编程语言的程序员来说, 接口这个名词一定不陌生, 但是不知各位有没有这样的疑惑: 接口有什么用途? 它和抽象类有什么区别? 能不能用抽象类代替接口呢? 而且, 作为程序员, 一定经常听到面向接口编程这个短语, 那么它是什么意思? 有什么思想内涵? 和面向对象编程是什么关系? 本文将一一解答这些疑问
1. 面向接口编程和面向对象编程是什么关系
首先, 面向接口编程和面向对象编程并不是平级的, 它并不是比面向对象编程更先进的一种独立的编程思想, 而是附属于面向对象思想体系, 属于其一部分或者说, 它是面向对象编程体系中的思想精髓之一
2. 接口的本质
接口, 在表面上是由几个没有主体代码的方法定义组成的集合体, 有唯一的名称, 可以被类或其他接口所实现 (或者也可以说继承) 它在形式上可能是如下的样子:
- interface InterfaceName
- {
- void Method1();
- void Method2(int para1);
- void Method3(string para2,string para3);
- }
那么, 接口的本质是什么呢? 或者说接口存在的意义是什么我认为可以从以下两个视角考虑:
1)接口是一组规则的集合, 它规定了实现本接口的类或接口必须拥有的一组规则体现了自然界如果你是则必须能的理念
例如, 在自然界中, 人都能吃饭, 即如果你是人, 则必须能吃饭那么模拟到计算机程序中, 就应该有一个 IPerson(习惯上, 接口名由 I 开头)接口, 并有一个方法叫 Eat(), 然后我们规定, 每一个表示人的类, 必须实现 IPerson 接口, 这就模拟了自然界如果你是人, 则必须能吃饭这条规则
从这里, 我想各位也能看到些许面向对象思想的东西面向对象思想的核心之一, 就是模拟真实世界, 把真实世界中的事物抽象成类, 整个程序靠各个类的实例互相通信互相协作完成系统功能, 这非常符合真实世界的运行状况, 也是面向对象思想的精髓
2)接口是在一定粒度视图上同类事物的抽象表示注意这里我强调了在一定粒度视图上, 因为同类事物这个概念是相对的, 它因为粒度视图不同而不同
例如, 在我的眼里, 我是一个人, 和一头猪有本质区别, 我可以接受我和我同学是同类这个说法, 但绝不能接受我和一头猪是同类但是, 如果在一个动物学家眼里, 我和猪应该是同类, 因为我们都是动物, 他可以认为人和猪都实现了 IAnimal 这个接口, 而他在研究动物行为时, 不会把我和猪分开对待, 而会从动物这个较大的粒度上研究, 但他会认为我和一棵树有本质区别
现在换了一个遗传学家, 情况又不同了, 因为生物都能遗传, 所以在他眼里, 我不仅和猪没区别, 和一只蚊子一个细菌一颗树一个蘑菇乃至一个 SARS 病毒都没什么区别, 因为他会认为我们都实现了 IDescendable 这个接口(注: descend vi. 遗传), 即我们都是可遗传的东西, 他不会分别研究我们, 而会将所有生物作为同类进行研究, 在他眼里没有人和病毒之分, 只有可遗传的物质和不可遗传的物质但至少, 我和一块石头还是有区别的
可不幸的事情发生了, 某日, 地球上出现了一位伟大的人, 他叫列宁, 他在熟读马克思恩格斯的辩证唯物主义思想巨著后, 颇有心得, 于是他下了一个著名的定义: 所谓物质, 就是能被意识所反映的客观实在至此, 我和一块石头一丝空气一条成语和传输手机信号的电磁场已经没什么区别了, 因为在列宁的眼里, 我们都是可以被意识所反映的客观实在如果列宁是一名程序员, 他会这么说: 所谓物质, 就是所有同时实现了 IReflectabe 和 IEsse 两个接口的类所生成的实例(注: reflect v. 反映 esse n. 客观实在)
也许你会觉得我上面的例子像在瞎掰, 但是, 这正是接口得以存在的意义面向对象思想和核心之一叫做多态性, 什么叫多态性? 说白了就是在某个粒度视图层面上对同类事物不加区别的对待而统一处理而之所以敢这样做, 就是因为有接口的存在像那个遗传学家, 他明白所有生物都实现了 IDescendable 接口, 那只要是生物, 一定有 Descend()这个方法, 于是他就可以统一研究, 而不至于分别研究每一种生物而最终累死
可能这里还不能给你一个关于接口本质和作用的直观印象那么在后文的例子和对几个设计模式的解析中, 你将会更直观体验到接口的内涵
3. 面向接口编程综述
通过上文, 我想大家对接口和接口的思想内涵有了一个了解, 那么什么是面向接口编程呢? 我个人的定义是: 在系统分析和架构中, 分清层次和依赖关系, 每个层次不是直接向其上层提供服务(即不是直接实例化在上层中), 而是通过定义一组接口, 仅向上层暴露其接口功能, 上层对于下层仅仅是接口依赖, 而不依赖具体类
这样做的好处是显而易见的, 首先对系统灵活性大有好处当下层需要改变时, 只要接口及接口功能不变, 则上层不用做任何修改甚至可以在不改动上层代码时将下层整个替换掉, 就像我们将一个 WD 的 60G 硬盘换成一个希捷的 160G 的硬盘, 计算机其他地方不用做任何改动, 而是把原硬盘拔下来新硬盘插上就行了, 因为计算机其他部分不依赖具体硬盘, 而只依赖一个 IDE 接口, 只要硬盘实现了这个接口, 就可以替换上去从这里看, 程序中的接口和现实中的接口极为相似, 所以我一直认为, 接口 (interface) 这个词用的真是神似!
使用接口的另一个好处就是不同部件或层次的开发人员可以并行开工, 就像造硬盘的不用等造 CPU 的, 也不用等造显示器的, 只要接口一致, 设计合理, 完全可以并行进行开发, 从而提高效率
本篇文章先到这里最后我想再啰嗦一句: 面向对象的精髓是模拟现实, 这也可以说是我这篇文章的灵魂所以, 多从现实中思考面向对象的东西, 对提高系统分析设计能力大有脾益
下篇文章, 我将用一个实例来展示接口编程的基本方法
而第三篇, 我将解析经典设计模式中的一些面向接口编程思想, 并解析一下. NET 分层架构中的面向接口思想
对本文的补充:
仔细看了各位的回复, 非常高兴能和大家一起讨论技术问题感谢给出肯定的朋友, 也要感谢提出意见和质疑的朋友, 这促使我更深入思考一些东西, 希望能借此进步在这里我想补充一些东西, 以讨论一些回复中比较集中的问题
1. 关于面向接口编程中的接口与具体面向对象语言中接口两个词
看到有朋友提出面向接口编程中的接口二字应该比单纯编程语言中的 interface 范围更大我经过思考, 觉得很有道理这里我写的确实不太合理我想, 面向对象语言中的接口是指具体的一种代码结构, 例如 C# 中用 interface 关键字定义的接口而面向接口编程中的接口可以说是一种从软件架构的角度从一个更抽象的层面上指那种用于隐藏具体底层类和实现多态性的结构部件从这个意义上说, 如果定义一个抽象类, 并且目的是为了实现多态, 那么我认为把这个抽象类也称为接口是合理的但是用抽象类实现多态合理不合理? 在下面第二条讨论
概括来说, 我觉得两个接口的概念既相互区别又相互联系面向接口编程中的接口是一种思想层面的用于实现多态性提高软件灵活性和可维护性的架构部件, 而具体语言中的接口是将这种思想中的部件具体实施到代码里的手段
2. 关于抽象类与接口
看到回复中这是讨论的比较激烈的一个问题很抱歉我考虑不周没有在文章中讨论这个问题我个人对这个问题的理解如下:
如果单从具体代码来看, 对这两个概念很容易模糊, 甚至觉得接口就是多余的, 因为单从具体功能来看, 除多重继承外(C#,Java 中), 抽象类似乎完全能取代接口但是, 难道接口的存在是为了实现多重继承? 当然不是我认为, 抽象类和接口的区别在于使用动机使用抽象类是为了代码的复用, 而使用接口的动机是为了实现多态性所以, 如果你在为某个地方该使用接口还是抽象类而犹豫不决时, 那么可以想想你的动机是什么
看到有朋友对 IPerson 这个接口的质疑, 我个人的理解是, IPerson 这个接口该不该定义, 关键看具体应用中是怎么个情况如果我们的项目中有 Women 和 Man, 都继承 Person, 而且 Women 和 Man 绝大多数方法都相同, 只有一个方法 DoSomethingInWC()不同(例子比较粗俗, 各位见谅), 那么当然定义一个 AbstractPerson 抽象类比较合理, 因为它可以把其他所有方法都包含进去, 子类只定义 DoSomethingInWC(), 大大减少了重复代码量
但是, 如果我们程序中的 Women 和 Man 两个类基本没有共同代码, 而且有一个 PersonHandle 类需要实例化他们, 并且不希望知道他们是男是女, 而只需把他们当作人看待, 并实现多态, 那么定义成接口就有必要了
总而言之, 接口与抽象类的区别主要在于使用的动机, 而不在于其本身而一个东西该定义成抽象类还是接口, 要根据具体环境的上下文决定
再者, 我认为接口和抽象类的另一个区别在于, 抽象类和它的子类之间应该是一般和特殊的关系, 而接口仅仅是它的子类应该实现的一组规则 (当然, 有时也可能存在一般与特殊的关系, 但我们使用接口的目的不在这里) 如, 交通工具定义成抽象类, 汽车飞机轮船定义成子类, 是可以接受的, 因为汽车飞机轮船都是一种特殊的交通工具再譬如 Icomparable 接口, 它只是说, 实现这个接口的类必须要可以进行比较, 这是一条规则如果 Car 这个类实现了 Icomparable, 只是说, 我们的 Car 中有一个方法可以对两个 Car 的实例进行比较, 可能是比哪辆车更贵, 也可能比哪辆车更大, 这都无所谓, 但我们不能说汽车是一种特殊的可以比较, 这在文法上都不通
来源: http://www.bubuko.com/infodetail-2527802.html