看了PetShop4.0的源码,里面有不少使用接口的例子,在可扩展性、减少耦合等方面似乎作用并不大,那为什么还要使用接口,直接定义使用类方便不少。大家对此有什么看法呢?

解决方案 »

  1.   

    在petshop中使用接口
    主要是针对以后的数据库平台转移便利。sql2000的数据库平台,都要实现该接口。
    oiracle的也要实现该接口。而BLL层只要通过工厂模式调用方法,返回一个接口。就可以操作了。而不用管数据库的变迁。
      

  2.   

    接口的好处:
    1)提供了一个调用约定及抽象,相关开发人员可以根据实际情况“分头”实现
    2)方便扩展,只需根据接口实现并通过相关机制“注册”或“载入”就可以。
    ...如果你不在乎系统将来可能面对的各种变化,也不在乎彼此之间有一个无关于实现的接口约定,那接口确实是没什么意义。欢迎大家来我的博客作客:http://blog.csdn.net/aafshzj/
    我正在写一系列关于AAF组件框架的文章。该框架能对开发工作提供很多帮助,并极大地提高开发效率。希望大家看一看并提出宝贵建议。
      

  3.   

    继承机制虽然支持abstract关键字,但是不支持多重继承,因此接口还无法淘汰。
      

  4.   

    接口和继承我基本都大量使用,而且我往往通过独立的Assembly定义对外提供的接口。而实现内部怎么写(前提是结构合理而清晰)都行。这样实际上也便于任务分解和管理。不然任务分解就是一句空话。接口某种意义上就是一个Contract,是将来与现在的合约,是平台与应用的合约,是开发小组与开发小组的合约,而跟实现无关。
      

  5.   

    能够仅仅使用接口,而不实现接口吗?不能!因此说“接口无关于实现”是含糊的。这就好像汇编语言与c++相比,有人说汇编语言是最高级的语言,因为c++能够实现的功能、观念,汇编语言都都能实现,因此汇编语言比c++高级。
      

  6.   

    在petshop中使用接口
    主要是针对以后的数据库平台转移便利。sql2000的数据库平台,都要实现该接口。
    oiracle的也要实现该接口。而BLL层只要通过工厂模式调用方法,返回一个接口。就可以操作了。而不用管数据库的变迁。
      

  7.   

    再说一遍吧,接口的最大意义就在于提供了“无关于实现的”协议,因此也就对变化提供了统一的协议和约定:“另外,二者本来并没有天渊之别。在实现上,接口和纯虚基类一致的。因为是纯虚,所以接口更偏向约定一些,而无关于实现。继承当然是兼而有之。但也正因为其兼而有之,当我只想约定,而不想约束实现时,接口就是最好的选择。”ruanbi的
    “你可以把类中变化的部分分离出来,放到接口里,然后用不同的类实现这些变化的方法
    在大类中你可以引用这些接口,然后实例不同的方法.挺好”实际上也是这种说法的一个诠释。至于“接口更偏向约定一些,而无关于实现”和是否就等于“接口完全和实现无关”。我觉得二者都是在特定上下文中讲的话,一个偏向于强调其结构及意义,一个偏向于最重的部署和实现。其正确与否并不矛盾,而且说实话偏题太远了也过于琐碎了。我的中心思想还是那句话::“接口和抽象类各有各的作用。二者各有各的适用条件”。至于分别在何处何时适用,我也已经讲了很多。接口自然不是放到哪里都行,但也绝不是完全可被别人替代的毫无意义的替代品。
      

  8.   

    接口,几乎是任何人都能理解的纯技术、简单的概念。但是可以任意使用接口!如何使用接口才算好?继承就是一种基于接口概念又高于接口的简化了编程的高级技术。因此当你使用接口的时候,我们知道你使用了接口而已。是不是你的程序逻辑流程真正具有继承性,你的代码是否很容易共享,还要额外考察。而对继承,直接从类型定义的关系上(继承性)上就能看出来了。.net framework或者java的那些类库,并没有将所有类型“都用接口重新定义一遍”,而是用接口作为类型的补充的。这是因为.net(以及java)与c++、Smalltalk、Eiffel等OO高级语言不同,不支持多重继承。
      

  9.   

    说继承是“约束了实现”,这是由于不理解“继承的时候还要重写父类的实现”造成的。如果承认继承机制包含了重写,那么也就找不出“约束了实现的毛病”。说个实际的,如果你想写一个自定义Calendar控件用于多态地完成自己的功能,例如把用户点击过的日期在日历上作记号并且保存到数据库,你会仅仅去“使用Calendar接口”吗,如果没有这个接口你就不去继承它吗?回过头来,我们看到那些写大型类库德实践者给我们一个结果,大量地使用类型继承,接口基本上作为是补充手段。
      

  10.   

    sp1234真够顽强的,呵呵。说二者各有各的适用条件都还要出来反驳。你的Calendar例子我看都不去看,最多说明那种场合不适用于接口,还能说明什么?要举出一个适用接口的例子是同样简单:就看一下支付渠道的例子:当电子商务系统有很多支付渠道,而且将来还会持续增加的时候,最好的做法就是把所有共性剥离出去予以实现,而把每次要增加的支付渠道的个性通过接口予以约定:“只要你提供这样的接口给我就行,具体怎么实现这些你自己去决定”。即便是.net本身也有很多接口。比如在Ado.Net里定义的大量接口:IdbCommand、IDataReader、IColumnMapping、IColumnMappingCollection、IDataAdapter、IDataParameter、IDataParameterCollection 等等。接口和抽象类本身就是各有各的适用条件,把二者简单的对立起来,说“继承就是一种基于接口概念又高于接口的简化了编程的高级技术。”是很武断的。滥用接口固然是为技术而技术的表现,该用接口而不用接口则是更加荒谬的。
      

  11.   

    我只想强调,接口是基础,而继承是高级应用。如果有多重继承并且可以有更多的手段对协议进行说明,写出的程序更加稳定。Eiffel被作为一种效率可比c++,而专门用于具有非常高的可靠性要求的软件开发领域,它没有接口,它让程序员把大量的精力放在对继承关系下的软件协议的描述上,它的需求分析、体系结构设计、详细设计、编码开发、测试程序等等完全使用这种语言来完成而不像我们在c#或者java之类的使用各种不同的软件工程工具。实际上越是高级的软件开发,其形式越是简单。可能仅仅需要10个关键字就够了,而c#肯定超过100个关键字。打个比方,当我们将全部精力放在去琢磨前进的路上有哪些休息的“点”的时候,聪明的行者早已经将规划和测试的重点放在点与点的“联系”的表达方法上了,因此采用了更加有表现了、看上去更简洁、更加敏捷的规划工具。
      

  12.   

    呵呵,我要说明一些东西,自然在选择论据方面有一些倾向性。但是并没有武断地对立起来,而是尽量说明他们联系、过去的历史和我所认识到的技术的将来走势。我们可以找出一些确实说明继承不适合而接口适合使用的例子来吗?(由于.net不支持多重继承而造成的必须使用接口的例子不算)
      

  13.   

    接口与继承(准取地讲是抽象类或类)各有适用的条件。接口最终一定要被某个类所实现,抽象类有时候也会把一部分责任通过接口予以约定。多重继承是一个争议话题,因为它确实很容易导致结构和理解问题,好处当然也是有的:在某些情况下确实可以减少代码冗余。不过冗余的问题说实话也不是那么严重,实际上很多时候通过“接口+ Composite另一个对象”的方式也能间接实现类似的效果。当然,肯定没有允许多重继承来得直接和简单。不过,这是另一个问题了,因为即便是在允许多重继承的情况下,接口仍然有其巨大的实际意义。.Net的反多重继承是来自java的。而java之所以如此,则是受到了c++时代开发社区对多重继承巨大争议的触动和启发。因此,在刚开始推出的时候,java最吸引人的地方就是简单。当然,这一点也已有所改变。java的演化过程也说明:关键字的多寡和形式的简单是相对的,随着特性需求的增长,一种语言肯定会越来越复杂,而直到其复杂性导致巨大的学习代价并且很多人开始对其感到“恐惧”。这时候就需要对语言进一步抽象予以简化。此后一种新的语言产生,大量新的特性又开始涌现...周而复始。简化-〉复杂-〉简化的循环并未改变,但是语言的抽象能力却越来越强。因此,从这个角度讲,高级语言确实会使得大多数问题变得简单,但是为了解决更复杂的问题,它本身还是会越变越复杂,直到下一次革命。世界就是如此,充满哲学气息。
      

  14.   

    “只要你提供这样的接口给我就行,具体怎么实现这些你自己去决定”关于这个,我要举个例子,DBCommand不但可以仅仅定义接口,而且也可以适当定义流程。而IDBCommand则只能定义接口。如果不是因为.net不支持多重继承,以至于不得不使用IDBCommand来让其它同时具有多种接口的类型使用,IDBCommand早就是多余的东西了。如果了解OO理论上的继承,而不是.net或者java的单重继承,如果从设计上去学技术而不是从技术上去学设计,就会很主动地去使用更加经济可靠、简单自然的技术,而避免纠缠入过多的技术术语。
      

  15.   

    当我们对某篇论文发生争议的时候,很自然有很多人从字典出发去研究争议的起因,就像今天我们发现c#的程序逻辑有争议的时候很自然会想到回到IL去研究、甚至回到机器码去研究。这很自然,这似乎可以类比地支持说接口有多么多么重要。我并不否认它的重要性。但是我也要说明一种更加重要的观念,我相信应用决定技术,而不是想反。基于此,今天被人们念念不忘但是并没有澄清编程技术的走向的那些概念,正像汇编语言早晚会被人们认识到是编程的障碍从而才出现了c、c++一样,也需要改变甚至被很多急功近利的学习者忘记,直接学习高级的技术,这样才能更加快速地创造出更多实用的组件,而不是在哪里研究底层概念。
      

  16.   

    IDBCommand当然不会是多余的,即便是允许多重继承也是如此。因为IDBCommand等接口的根本意义在于ADO.net提供了一个Provider(可能是第三方的)的统一“外表”,而不是什么“让其它同时具有多种接口的类型使用”。我是从C开始编程的,经历了C++\java\c#,我的观点已经很清楚:接口或者说“纯虚基类”总是有其特定的适用范围和意义的,而无论语言是否支持多重继承。
      

  17.   

    再拿c#3.0来说吧,它不过是几个至关重要mis系统的引擎驱动程序而已,但是它就是作为一个单独的“版本”发布出来了。你能够只能够了解它的接口概念吗?不是,你必须了解它的流程。
      

  18.   

    唉,上边没有理解我的意思。我问:为什么在提供 IDBCommand 接口之外还要提供 DBCommand 类型?为什么不把这个责任推卸给每一个程序员自己去实现?你可能会很轻蔑地嘲笑我为什么会问这么浅显的问题。这其实正是我要提醒大家注意的。
      

  19.   

    难道你认为接口的意义就是这些:“IDBCommand 接口之外还要提供 DBCommand 类型?为什么不把这个责任推卸给每一个程序员自己去实现?”如果你这样理解接口,那我可以负责任地告诉你:“你理解的这种接口确实没什么意义”。
      

  20.   

    OO的原则,面向接口编程,还不是面上类编程。接口是实现插接性基本。没有接口,Eclipse的插件如何实现?
      

  21.   

    那么什么情况下适合于接口而不适合于继承?请说明。当然,除了我在上边说过的.net的缺点:“继承机制虽然支持abstract关键字,但是不支持多重继承”除外。
      

  22.   

    注意,这个帖子并不是讨论是否应该删除接口,而是讨论“那为什么还要使用接口,直接定义使用类方便不少”。这其中包括abstract关键字说明的类。我不关心结论,关心的是过程。
      

  23.   

    “难道接口不是一种最直接的方式吗?”自然是一种最直接的方式呀!但是不是直接了当的方式!抱着字典去看小说是一种最直接的方式呀,每一个字都认识,但是并不一定就意味着对应用清楚,因此并不是“了当”的方式。PetShop4是一种一看就是相当结构化的设计的风格(我接触的一般程序员90%都是如此),不是.net framework之类的复杂系统的设计风格,这些复杂系统相当地OO。仔细读过他们,进行对比就能有所体会。
      

  24.   

    使用类型,既可以abstract,既可以定义接口、也可以定义流程,定义可以传递给子类(而接口不具有传递性),这是“谁更省力”的最好表达。我很想引出aafshzj(上海北京) 来说说“接口比类型更加省力”的比较翔实的论据来,可惜除了看到对接口的好处的描述(这些好处对类型一样适用),并没有看到独特性。
      

  25.   

    当我们设计系统的时候,从OO理论上说所谓“接口”的时候,借口并不是interface,而是指类型的属性或者方法定义。OO并没有去考虑interface这种具体的编程语言或者平台的具体实现。知道这个很重要。楼主的“有无必要使用接口”的疑问我是非常支持的,并且我提供了一些信息,说明更加高级的编程语言是不使用interface的,只不过微软没有采用它作为自己的主流开发平台而已!
      

  26.   

    呵呵,OO理论上的接口就是"interface",一字不差,只不过不限于C#或者.Net的interface罢了。同时,语言级的接口也只是理论级的接口的一个实现罢了。至于高级语言应不应该提供interface,那也是见仁见智的事情。何况因为你认为的某种高级语言可能不提供接口就以此说明Interface没有意义,这本身就已经深深陷入了“为了技术而技术”的渊薮。相反,澄清一下到底什么场合适用接口才是真正有价值的。
      

  27.   

    其实我并没有讨论“什么场合不适用接口”的问题,我对这个不感兴趣。我只是说明“直接定义使用类方便不少”,并且借此说明为什么结构化倾向于interface而拒绝继承。
      

  28.   

    sp1234(警惕“败事有余”,容忍“成事不足”):1.我赞同应该有多重继承(真正的类的多重继承)。2.你刚才问:"能不能举出个例子证明哪个地方只适用于接口,不适用于抽象类?"
    我的观点是:
    interface能实现的,abstract类也能实现(假如有多重继承),而interface只是比abstract类更抽象。
    我觉得关键是有不有地方确实需要这种仅仅只要方法声明,不需要任何实现的类型,我觉得是有的,并且很多。interface带来的便利本来就是设计上的,而不是功能上的。就好比假如没有抽象类,普通类一样可以完成抽象类的工作一样。
    没有哪个地方只能用抽象类,而不能用普通类去替代。
      

  29.   

    不用将interface和class共有的好处作为interface独有的好处,而要说明class的坏处。class有abstract、sealed、virtual等等修饰手段,但是由于.net的语言水平还没有到支持多重继承的地步,自然少不了接口。这个我很清楚。
      

  30.   

    其实我并没有讨论“什么场合不适用接口”的问题,我对这个不感兴趣。我只是说明“直接定义使用类方便不少”,并且借此说明为什么结构化倾向于interface而拒绝继承。=================================================
    呵呵,有时候“直接定义使用类方便不少”,我从来就不反对,也符合我的各有条件之说。但不总是如此,有的时候用接口能够明显的降低结构及代码的耦合度和维护成本,同时,提供较低成本的系统扩展方法。
    好吧,不管我们俩今天的讨论从哪来开始的。周末了,今天的讨论就到此结束吧,大家周末愉快!
      

  31.   

    interface是基础,自然是万能的。就像是我们现在使用的都是同一种系统的计算机,这种体系下的计算机“内存地址”是万能的,但是我们的编程理念已经进化到防止这种“万能”的观点,而是将它约束为面向领域功能的更加清晰可靠的几种类型上了,我们现在使避免使用“万能”的内存地址指针。.net的class的功能还是比较弱的,而不是很强的,更不是多余和只要有inetrface就够了的。注意到可以简化设计,腾出精力,可以多考虑研究class之间的关系、控制、适配等流程问题,而不是概念。
      

  32.   

    哦对了,顺便说明一下,凡是会写到分布式系统的人都要了解到:定义分布式的对象的时候(服务端和客户端的协议)要使用class不要使用interface,否则你的系统会在写了很多东西之后不得不把中间接口重新改为抽象class。
      

  33.   

    你的“分布式”说法就算成立也顶多多找出了一个接口可能发挥不了什么作用的场合罢了。何况,你的“分布式”说法本身就不成立。SOA算不算一种“新形势”下的分布式系统?很多人就把SOA看作“基于接口的设计”。因为SOA的核心确实就是将业务逻辑通过XML定义的接口合约明确下来。各服务之间完全基于这个合约进行整合和集成。SOA的例子恰恰说明了接口并不限于C#或者java的接口,而有其更普遍的意义。
      

  34.   

    显然这个帖子是讨论“那为什么还要使用接口,直接定义使用类方便不少”的。我一直记着这个题目,并且我是针对你所不知、不注意的东西而说的,而不是在说你知道的那些有什么错误。我们并不需要学究气,我们仅仅需要知道“哪个更方便”,而不用去讨论“对错”问题。如果说“使用接口就足够好”了,那么我就完全明白你的意思了!问题是你一直强调接口如何如何好,而并没有说出它比类型好在那些方面,我是担心读者因此有误导,以为一个如此简单的东西是万能的、最好的、最适宜的!“我不会在不该使用接口的时候使用接口,更不会在该使用接口的时候不使用接口。”这句话我的建议是优先考虑一下“为什么还要使用接口,直接定义使用类方便不少”。接口是定义了对象的某一个方面,而.net的类型定义了对象的全部公开信息,这是不同的。设计分布式对象的时候,如果客户端没有这个信息,当A是B的客户并且对象从B产生而传递给A的时候没有任何问题,但是如果是B再从C取得(从C产生传递给B)再传递给A的时候,基于interface的程序不会出现任何编译错误(因为接口是不完全的信息,编译器并没有足够资料验证设计错误),但是会出现运行时错误。
      

  35.   

    “各有其适用条件”,那么请说明适合接口而不是和类型的条件,这是我一直想引你说清楚的。(当然除了“多重继承”的场合除外,我也没听你说过这方面的)你曾经说过“避免约束实现”,我问过你“abstract、sealed、virtual等简单功能的类型怎么就约束实现了”,但是没有回应。
      

  36.   

    既然我说:“有的时候用接口能够明显的降低结构及代码的耦合度和维护成本,同时,提供较低成本的系统扩展方法。”你回答:“从来没有反对过这种说法。...”
    那不就对了吗,看看我们从哪里开始争论到现在。我从一开始就说“各有适用场合”,那你为什么还要和我争论呢? ^_^你自己都已经有了上述这番话,还有必要还要再举吗?但是既然你要,既然你觉得有必要,我也就再去找来贴一遍:1)==========================
    何况,你的“分布式”说法本身就不成立。SOA算不算一种“新形势”下的分布式系统?很多人就把SOA看作“基于接口的设计”。因为SOA的核心确实就是将业务逻辑通过XML定义的接口合约明确下来。各服务之间完全基于这个合约进行整合和集成。SOA的例子恰恰说明了接口并不限于C#或者java的接口,而有其更普遍的意义。2)==========================
    就拿我前面说的支付渠道的例子,当我把支付渠道德所有共性剥离出去,而抽象出独立的“支付渠道驱动接口”来建立平台有关支付渠道的扩展机制的时候,难道接口不是一种最直接的方式吗?直接了当的方式?难道我把今后不能预见的东西都实现了,或者一定要实现一些我想不到的功能,然后丢一个基类给别人去扩展,而且不但要解释扩展部分(其实类似于接口)的约定含义还要暴露不必要细节地解释已经有的属性和方法(除非全是私有,可如果已有属性和功能全都是私有,我为什么不通过一个虚基类也就是接口把它们封装起来,而把各接口实现这一有更大变化可能性的可变部分剥离出去以便降低维护成本呢)与其扩展部分之间的复杂关系才叫着接了当?3)===========================
    比如在Ado.Net里定义的大量接口:IdbCommand、IDataReader、IColumnMapping、IColumnMappingCollection、IDataAdapter、IDataParameter、IDataParameterCollection 等等。IDBCommand当然不会是多余的,即便是允许多重继承也是如此。因为IDBCommand等接口的根本意义在于ADO.net提供了一个Provider(可能是第三方的)的统一“外表”,而不是什么“让其它同时具有多种接口的类型使用”。==========================至于“避免约束实现”我没说过,我的原话是“但也正因为其兼而有之,当我只想约定,而不想约束实现时,接口就是最好的选择。”其意义自己结合其上下文去看吧。至于你说的“abstract、sealed、virtual”这些东西对继承实现有没有影响本来是显而易见的:当我提供一个接口给别人的时候我只要把接口本身内部的关系解释清楚就可以了。当我用virtual的时候,我就必须让底层了解基类的实现逻辑大致是怎样的,何种条件下是应该被衍生类型替换的。这在有时候是没有办法改变的事情,但是在那些可以将一个类型其中的可变部分完全以接口形式确定下来而代价很小(比如根本不会或者很少产生代码冗余)的时候,我就可以把接口的实现通过接口与其它部分的实现清晰地“干净地”切割开来,从而在一个局部在很好地解决这种问题。
      

  37.   

    我提供一个接口给别人的时候我只要把接口本身内部的关系解释清楚就可以了。当我用virtual的时候,我就必须让底层了解基类的实现逻辑大致是怎样的,何种条件下是应该被衍生类型替换的。
    ————————————————————————————————————————
    使用接口就不需要“底层了解基类的实现逻辑大致是怎样的”的吗?这么说实现接口的类型随意实现接口,只要编译通过就行?提交被别人一个class的时候,为什么“只要把class本身内部的关系解释清楚”就不够呢?其实interface仅仅在“强迫程序员去自己写代码实现接口”这个方面与class不一样,在对程序员对协议的理解的说明方面没有任何区别。interface不实现内部程序,把这个说成是自己的优点(不需要了解实现),有class既可以继承也可以virtual,明明将实现方法隐藏了起来提供继承却被inetrface说成是“硬要程序了解实现内容”。
    你的说法我在XingChen的书上似乎见过,似乎是抄来的。总的来说,我觉得他的那本书是很好的,很难的地,搞框架设计的人都应该读一读作为入门。但是他竟然把继承用这样做比喻:“父亲把遗产给了儿子”!这显然是乱伦的比喻。继承是说父子都是“同一个”实体,例如医院病人张三就是住院部病人张三,是同一个人,这才是继承。他的书设计模式很多,但是OO很少。
      

  38.   

    现在通篇讲设计模式,但是骨子里对OO用结构化去做解释的书,其实已经很少了。XingChen的书《.net平台应用框架的设计与实现》结构清晰,并且是围绕着.net framework的源代码展开,所以深度不错。但是OO方面有欠缺。
      

  39.   

    接口作为一种底层的简单工具,OO还是伪OO的人都乐得去使用它,因为它并不体现设计和实现方法上的分歧。但是往细节里看的人,就会发现伪OO的那些程序“在可扩展性、减少耦合等方面似乎作用并不大”。
      

  40.   

    你没有你没看懂我在说什么,我再解释一下吧。“至于你说的“abstract、sealed、virtual”这些东西对继承实现有没有影响本来是显而易见的:当我提供一个接口给别人的时候我只要把接口本身内部的关系解释清楚就可以了。当我用virtual的时候,我就必须让底层了解基类的实现逻辑大致是怎样的,何种条件下是应该被衍生类型替换的。这在有时候是没有办法改变的事情,但是在那些可以将一个类型其中的可变部分完全以接口形式确定下来而代价很小(比如根本不会或者很少产生代码冗余)的时候,我就可以把接口的实现通过接口与其它部分的实现清晰地“干净地”切割开来,从而在一个局部在很好地解决这种问题。”所有权衡都是有量的概念的,而不一定是你有我没有或者你没有我有的关系。如果我有一个虚基类(但不是纯虚)有18个方法,其中9个提供了基类实现并且允许基类override,另外9个纯粹是Abstract的。这个基类存在多个衍生类,但这些衍生类还是没有实现那9个方法,而把那9个方法留给将来某种扩展自己其实现。当将来其它人员实现A的基类时,我是不是不仅仅需要把9个虚方法的意义解释一遍,还要把9个已经实现它们可以override的方法也解释一下?另外,解释方法及其实现容易还是仅仅解释方法声明容易点?当然你还说,你那9个已经实现的总要和维护人员解释的。但是问题就在于清晰的分解,如果维护工作量(不考虑两种方式导致的差别)需要4个人维护。是在物理上根据代码明确划分成两个维护接口的实现部分,两个维护衍生类实现部分的解释、沟通、管理成本低,还是不用接口的只是在职责上划分的解释、沟通、管理成本低?这个问题不用我们回答,让各位读者自己结合自己的实际经历去回答。这种情况下,如果把这9个方法提取出来作为一个接口(纯虚基类)单独约定。我就只需要解释这个接口的9个方法每一个分别是什么意义。是解释18个方法的声明以及9个方法的实现容易还是解释9个方法的声明如下。说白了,接口的存在意义和虚基类的存在意义是一样的,有时候,就是虚基类更自然。就拿支付渠道的例子来说,我就是只能确定将来的渠道驱动要提供这样几个方法,就是没有什么好帮它实现的,于是就把它实现为虚基类不是最自然而然吗?这不是一定要接口或者一定不要接口的问题。基本上所有的接口实现都可以被改成非接口实现,同样所有的非接口实现也可以生生把接口插进去。问题在于在哪一种情况下何种方式的代码更容易理解、更容易维护、代码冗余更小也更自然。最终的取舍就取决于这诸多要素的综合权衡。
    呵呵,好了,这个问题说了够多了,翻来覆去也讲了很多。请楼主择吉结贴吧。问题的答案大家自己去判断,我也不再回帖了。各位周末愉快,回家了。
      

  41.   

    可以把接口和继承看成两个东西。继承是从类继承的,你继承一个类的功能肯定希望把相关的实现一起继承才对。
    所以说接口和继承是两个概念。接口是鸭子类型的蹩脚实现。
    什么是鸭子类型,鸭子类型可以这样描述,如果一个东西叫声象鸭子,走路像鸭子,长得也像鸭子,那它就是鸭子。放到类上,一个类型如果具备某个抽象类型所有的公开接口,那它就应该是那个抽象类型。可以执行SQL命令的类就应该是IDbCommand,但是C#严谨的语法要求必须显示的声明一下,这就是接口了。
      

  42.   

    aafshzj(上海北京)
    > 接口某种意义上就是一个Contract,是将来与现在的合约,是平台与应用的合约,是开发小组与开发小组的合约,而跟实现无关。客气了,接口就是 Contract,是更抽象的层次——等同于纯抽象类,只不过因为C#/Java等不支持多重继承的情况下,用接口来代替了纯抽象类>sp1234(3+1=无穷大)
    “IDBCommand 接口之外还要提供 DBCommand 类型?为什么不把这个责任推卸给每一个程序员自己去实现?”此言差矣,你可以“实现”接口,却不能继承接口——正是因为接口等同于纯抽象类,它们俩都不能提供复用代码的好处,所以在某些情况下,包括你说到的分布式系统或者 aafshzj(上海北京) 举的例子以及 DBCommand 来看,接口配合抽象类的使用来完成这一工作:即提供抽象约定,又提供代码复用——前者由接口/纯抽象类负责,后者由抽象类/类负责。
    那么,如果你不需要提供更高层次的抽象,那就没必要使用接口,抽象类/类就够了。抽象类和接口的差别以及何时使用的问题,可以从极端情况来看:
    1、比较 接口 与 纯抽象类——可以得知,它们在继承层次上是最高级别,不同的地方在于语言是否允许多重继承——允许,那就没有区别了
    2、如果想在约定(定义抽象约束)的同时提供代码复用,因为接口没有实现代码不支持继承,此时应该用类,甚至是抽象类,但肯定不是纯抽象类至于,接口是结构化的,与 oo 无关——这样的概念似乎不正确吧
    对于一个“学生”类,可能实现了 IMan 接口,实现了 IStudent 接口,哪怕接口中什么也没有定义,那么这样的接口难道不是用来表达 is 关系的么?这难道不是 OO ?我同意你的观点,接口的引入的确是为了弥补不能多重继承的“不足”。但我不认为这是“不足”——java/C# 这么设计,恰恰是取了接口的好处,避免了多重继承的麻烦
    你可以保留意见认为多重继承就是比采用接口的方案好但事实上,对于多重继承的依赖,恰恰体现了对于“复用”的依赖,甚至可能滥用。
    使用接口,恰恰在很大程度上让我们的设计思路回归到设计本身,而不是代码复用。所以,有位朋友说得好:接口用来做设计,类用来复用代码——大概意思,不记得了,呵呵