对于同一类的不同实例之间,必定具有如下特点 相同的操作集合 相同的属性集合; 不同的对象名 2.3.3类的确定与描述 类的确定是采用归纳的方法,从对所遇到的对象的分析中,归纳出共同的特征来确定一 个类 例如我们可以通过对许多马的归纳总结,抽象出各种马的共同特征,从而得到马类 在实际工作中,单纯地描述一个独立的对象如何工作是没有任何意义的,往往是描述 个类的工作。如何来描述,不同的面向对象程序设计语言具有不同的描述工具。在C++中 没有类的描述文件,因此在程序中定义起来非常方便,下面是用C++语言对马类的描述 class horse 4 har* 练习题 (1)解释以下概念 ①对象,②消息,③类,④实例,⑤公有消息,⑥私有消息,⑦消息序 (2)对象有哪些特性? (3)对象是如何确定和划分的? (4)类与实例的关系如何?
围面向对系券胜 面向对象系统最突出的特性就是封装性继承性和多态性。衡量某一种程序设计语言, 看它是否是面向对象的程序设计语言,主要看它是否具有这三种持性在这一章中我们将对 它们逐个地进行分析。 3.1封装性 3.11什么是封装 从字面上理解封装就是将某事物包围起来使外界不知道其实际内容 在程序设计中,封装是指将…个数据和与这个数据有关的操作集合放在一起,形成一个 能动的实体——对象,用户不必知道对象行为的实现细节,只需根据对象提供的外部特性接 口访问对象即可因此,从用户的观点来看,这些对象的行为就像包含在一个“黑匣子”里,是 隐蔽的、看不见的 从上面的叙述我们看出,封装应该具有下面几个条件 ①具有一个清楚的边界,对象的所有私有数据、内部程序(成员函数)细节都被固定在 这个边界内。 ②具有一个接口,这个接口描述了对象之间的相互作用请求和响应,它就是消息。 ③对象内部的实现代码受到封装壳的保护,其它对象不能直接修改本对象所拥有的数 据和代码。 3.12什么是协议 协议是一个对象对外服务的说明,它声明这个对象可以为外界做什么。它是由一个对象 能够接受并且愿意接受的所有信息构成的对外接口。也就是说,请求对象进行操作的唯一途 径就是通过协议中提供的消息进行的 例如,一个人有各种能力,其中有一部分能力他乐意向外界公布并对外界提供服务;还 有部分能力只是有选择地向某些人宜布;还有一部分能力他不想让任何人知道,即使外人知 道了他所具有的这部分能力,他也不向他提供服务。这里就存在一个协议的问题,我们可以 将能眵提供服务的那部分能力写到协议中去 外界对象能够并且只能根据该对彖发送协议中所提供的消息,请求该对象服务。即使 个对象可以完成某一功能,但它没有将该功能放入协议中去,外界对象依然不能请求它完成 这一力能。协议实际上是一个对象所能接受的所有公有消息的集合 下面是一个用C++语言所定义的对象类
changma protected nt getmanκ(); 在上面所定义的学生对象类中包含的数据内容有学生姓名分数、专业。 它所包含的操作(所具有的功能)分为三种: ①处于私有段( private)的 changeman,这是不向外界公开的功能,只供对象自己使 用 ②处于保护段( protected)的 remark,这是只向部分外界宣布的功能,只对其派生类对 象提供服务。 ③处于公有段( public)的 gerace和 getmajor,这是向所有外界公开的功能,它可以响 应外界对象的请求,这些是属于协议的内容。 31.3面向对象系统的封装性 面向对象系统的封装性是一种信息隐藏技木,它使系统设计员能够清楚地标明他们所 提供的服务界面,用户和应用程序员则只看见对象提供的操作功能,看不到其中的数据或操 作代码细节 从用户或应用程序员的角度看,对象提供了一组服务而服务的具体实现即对象的内部 却被屏蔽封装着 对象的这一封装机制的目的在于将对象的使用者与设计者分开,使用者不必知道对象 行为实现的细节,只需用设计者提供的协议命令对象去做即可 面向对象系统中的封装单位为对象即主要指对对象的封装该对象的特性是由它所属 的类说明来描述,除去对象的封装以外类概念本身也具有一种封装意义它将数据和与这 个数据有关的操作集合封装在一起建立了一个定义良好的接口,这反映了抽象数据类型的 思想 32继承性 32.1继承的引人 继承是面向对象系统中的另一个重要的概念。在前面,我们讨论了类,这些类是孤立的 相互之间还没有建立关系,也就是说这些类都处在同一级别上是一种平坦结构。而这种没 有相交关系的平坦结构限制了面向对象系统的设计,这是因为它不允许类之间实现信息共 享在系统中有些对象,它们有一些相同但又有些差别如果不允许类之间建立相交关系,这 些不同对象的相似之处就无法表现出来 20
继承所表达的就是一种对象类之间的相交关系。它使得某类对象可以继承另外一类对 象的特征和能力。 若类间具有继承关系,则它们之间应具有下列几个特性 类间具有共享特征(包括数据和程序代码的共享) 类间具有细微的差别或新增部分(包括非共享的程序代码和数据) 类间具有层次结构。 具体地讲,若类B继承类A时,则属于B中的对象便具有类A的一切性质(数据属性 和功能(操作)我们称被继承类A为基类或父类,或超类而称继承类B为A的派生类或子 类。因此,要构造一个新类B,只需去继承一个与之有共同特征的基类A,再描述与基类不同 的少量特征(即增加一些新的数据成员和成员函数)。于是,类B便由继承来的和新添加的 两部分特征组成 继承所具有的作用有两个方面:一方面可以减少代妈冗余;另一方面可以通过协调性 来减少相互之间的接口和界面 322继承的分类 继承的分类可从下述两个方面考察 1.从继承源上划分 即从系统研究的角度来分,继承分为单继承和多继承例如一个人只能继承一个人的财 产,这就足单继承例如个人既可以继承父的财产,又可以继承其他亲属的财产,这就是 多继承, 2.从继承内容上划分 继承可分为取代继承、包含继承、受限继承和特化继承。 (1)取代继承例如徒弟从其师傅那里学到师傅的所有的技术,则在任何需要师傅 的地方都可以由徒弟来代替,这就属于取代继承。 (2)包含继承例如“水果”是一类对象“苹果”是一种特殊的水果。“苹果”继承了 水果”的所有持征任何一个苹果都是一个水果这使是包含继承。即苹果包含了水果具有 的所有特征。 3)受限继承例如,“鸵鸟”是一种特殊的鸟,它不能继承鸟会飞的特征,这就是受 限继承 (4)特化继承例如,“工程师”是一类特殊的人,他们比一般人具有更多的特有信 息,这就是特化继承 从上面继承分类的两个方面可以看出,所有的继承关系都存在类与类之间,而且都具有 两类不同的性质,一类是用来描述继承源的(单继承和多继承就属于此类);另一类是用来描 述继承内容的(取代继承、包含继承、受限继承和特化继承就属于此类)。 32.3继承与封装的关系 在面向对象系统中,有了封装机制以后,对象之间只能通过消息传递进行通讯;那么,继
承机制的引入是否削弱了对象概念的封装性,继承和封装是否矛盾。其实这两个概念并没有 实质性的冲突,在面向对象系统中,封装性主要指的是对象的封装性,即将属于某一类的 个具体的对象封装起来,使其数据和操作成为一个整体 在引入了继承机制的面向对象系统中,对象依然是封装得很好的实体,其它对象与它进 行通讯的途径仍然只有一条,那就是发送消息。类机制是一种静态机制,不管是基类还是派 生类,对于对象来说,它仍然是一个类的实例也许是基类的实例,也许是派生类的实例,因此 继承机制的引入丝毫没有影响对象的封装性。 从另一角度看,继承和封装机制还具有一定的相似性,它们都是一种共享代码的手段。 继承是一种静态共享代码的手段,通过派生类对象的创建,可以接受某一消息启动其基类所 定义的代码段,从而使基类和派生类共享了这一段代码。而封装机制所提供的是一种动态共 享代码的手段,通过封装,我们可将一段代码定义在一个类中,在另一个类所定义的操作中, 我们可以通过创建该类的实例,并向它发送消息而启动这一段代码,同样也达到了共享的目 的 32.4继承与委托的关系 委托是面向对象设计中经常使用的一种方法在面向对象系统中,每个操作元素都是 个对象,为了减少一个操作的实现代码,我们尽量使用向其它对象发送消息而不再重写代 码,这就是委托的意义。这意味着在定义一个对象的操作时要委托该操作所涉及的其它对 象完成部分操作来实现 继承和委托的相同点是,都具有节省代码的作用,继承定义的类可有继承其它类的能 力;委托则是一个对象可以依赖其它对象为它完成某些操作。 但继承和委托又是性质不同的两种关系。继承是静态关系,在程序描述时建立,它的基 本功能是将一些功能相关的对象进行特定归类表示,使得特殊类别的对象有继承较为一般 类别对象的能力;而委托则是一种既可以静态定义也可以动态定义的更复杂的关系,它的基 本功能是将一个对象的工作分配到与之相关的更特殊的对象上。 3.2.5类的层次 在前面已经介绍了继承的概念,当一个类B从类A中派生出来B类继承了A类的部 分或全部属性,B类作为一个派生类,它又可以再派生新类这样我们可以从某一个类派生 出所需的任意多的类,这就形成了类的层次。 下面是C++语言中派生类的定义, class class B: public A i class C: public B