Java-面向对象编程-2.ppt_第1页
Java-面向对象编程-2.ppt_第2页
Java-面向对象编程-2.ppt_第3页
Java-面向对象编程-2.ppt_第4页
Java-面向对象编程-2.ppt_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java程序设计 2 面向对象程序设计的特点 面向对象程序设计具有三大特征 封装继承多态 封装 封装 隐藏内部细节 控制外部访问的方式恰当的封装可防止程序员相互干扰 实现了模块化和信息隐藏通过控制对 内部 属性和方法的访问方式来实现封装不要依赖于你不需要知道的知识类和包是Java语言中的基本封装机制类实现了数据和方法的封装包是对一组相互耦合度较高的类型的封装 访问控制修饰符 JAVA中的访问控制修饰符public protected package 缺省 private 关联和聚合 对象不是孤立的关联 Association 两个对象间存在某种语义联系方向性 关联可以是单向的 也可以是双向的单向关联 A 知道 B 但B不 知道 A双向关联 A 知道 B B也 知道 A依赖性 不完全依赖A 知道 B 因此A依赖于B这种依赖一般是松散的 即A和B的存在都不需要以对方的存在为基础实现时 一般通过保存对方的对象标识来表达 关联和聚合 关联 Association 的UML表示 关联和聚合 聚合 Aggregation 表示两个对象间有整体 部分关系一种特殊的关联对象间的聚合关系总是单向的依赖性 依赖较强B是A的一部分 如果A聚合B has A关系 将B从A中取出 则A往往变得不完整一般情况下 B可以独立于A而存在换句话说 在系统内部存在一个A和B同时都独立存在的暂时状态 当然此时聚合对象的功能不完整 实现时 一般通过在A中保存B的对象标识来表达 关联和聚合 聚合 Aggregation 的UML表示 aStudent aSchedule 关联和聚合 复合 Composition 一种更强的聚合关系 特殊的聚合 对象间的复合关系总是单向的依赖性 部分的生命周期依赖于整体B不能独立于A而存在B的生命周期受A的控制 B会随着A的创建而创建 随A的消亡而消亡 实现时 一般通过在A中保存完整的B对象来表达B对象的实例化在A中完成 关联和聚合 复合 Composition 的UML表示 aTree aLeaf 关联和聚合 练习 以下各组对象之间应是哪种关联关系 学生 课本教师 学生书 前言书 作者汽车 引擎PC CPU深圳大学 深圳大学软件学院顾客 合同 继承概述 类与类之间还有一种Is A关系 子类自动获得父类的方法与属性 我们称之为继承子类拥有父类的一些公有的属性和方法 并且子类可能也会有自己的方法和属性派生与抽象 特化与泛化除了添加父类中没有的新方法外子类还可以通过重写父类的方法来重定义自己的行为方式 继承基础 重写与重载不同 重载需要不同的参数来区别相同方法名的方法 重写是发生在子类与父类上 重写父类方法必须与父类的方法名同名同参并且同返回值 当访问修饰符为private时 表明该方法不能被重写 同样当方法具有final关键字时该方法不能被重写 子类虽然重写了父类的某个方法 但仍然需要用到父类的这个方法 这时使用super关键字仍然可以调用父类的方法 TestOstrich javapublicclassTestOstrich publicstaticvoidmain String args Birdostrich1 newOstrich 向上转型ostrich1 fly classBird publicstaticvoidfly System out println BirdFlying classOstrichextendsBird publicstaticvoidfly System out println Ican tfly 输出结果 BirdFlying Static方法不能重写 Bird类派生了鸵鸟Ostrich类 以上程序声明了一个Bird类型的鸵鸟对象 象基本类型数据的自动提升一样 鸵鸟自动提升为Bird类 这叫做向上转型 static方法是不会被重写如TestOstrich java所示 子类中定义了与父类同名的fly方法 父类的fly方法不会被重写 而是被遮蔽因此得出结果鸵鸟会飞 构造方法的调用顺序 子类在产生对象实例时首先会调用父类的构造方法 如果没有显示的指定调用父类自定义的构造方法 那么编译器会调用默认的父类构造方法 super 但是父类如果自定义了带参数的构造方法 就必须在子类的构造方法中指定调用它 否则会因找不到super 而报错 注意 如果需要显示的调用父类构造方法 必须将其写在构造方法里的第一行 接着按声明的顺序调用成员初始化 最后调用本构造方法的方法体 Object类 Java中所有的类都是继承自一个老祖宗 Object类 它们都是Object类的子类 如果一个类在声明时没有用extends关键字显式的指定继承自某个基类 则Java隐式的指定它的默认基类为Object类 这种强制的继承模式叫做单根继承模式 单根继承使得Java简化了许多操作 基于单根继承 所有的对象都可以像基本数据类型一样向上转型到根层次上而使其操作上一视同仁单根继承的优势还在于可以在Object类定义所有对象都通用的方法 所有类都会自动继承这些方法 toString方法 Object类定义了publicStringtoString 方法 返回值是String类型 每当个对象都会有个toString方法 作用就是描述对象的信息要想使用toString方法必须按自己的需求重写这个方法 对象的比较 Java中比较两个基本数据类型变量的值时很简单使用 操作符Object类中的equals方法提供了对象内容的比较方法同样我们要是用这个方法必须重写它如果不重写equals方法 将调用object类的equals方法 Object类的equals方法相当于 为什么要继承 继承 概念的引入最早出现于Simula67语言需要继承 因为它支持更丰富 更强大的建模 有利于重用它可以在一个类中定义信息和行为 在相关子类中共享这些定义继承是很自然的使用继承 可以在已有类的基础上扩充 建立新类抽取一组类中的共同信息和行为 并同时保持类型安全 进行抽象 对类进行约束 设计类层次结构 自顶向下根据需要逐步扩充自底向上寻找相同点和相异点逐级抽象继承的表示法 一条带有空心大箭头的有向实线 箭头指向父类标识继承关系的原则 LSP Inheritanceshouldensurethatanypropertyprovedaboutsupertypeobjectsalsoholdsforsubtypeobjects Liskov 1987 多重继承 为什么引入多重继承 多重继承的优点功能强大允许私有继承更接近真实世界允许混合 mix in 多重继承的缺点复杂 有时难以理解导致名字冲突 二义性 重复继承编译器和运行时实现困难 示例 摘自ARM TheAnnotatedC ReferenceManual Addison Wesley 1990 classLottery public virtualintdraw classGraphicalObject public virtualintdraw classLotterySimulation publicLottery publicGraphicalObject 没有声明draw LotterySimulation pls newLotterySimulation pls draw 编译错误 classB classC classD publicB publicC 往往最后会发展成象下面这样 classA classB virtualpublicA classC virtualpublicA classD publicB publicC 问题是 设计类A和类B时 能否知道它们会被同时继承 多重继承 如何替代多重继承 Java C 等语言中的 接口聚合面向方面编程 AOP 范型 类属 继承与聚合 继承与聚合都可用于扩展类的功能和进行重用继承通过扩展一个已有类的实现 从而获得新功能泛化类 超类 可以显式地捕获那些公共的属性和方法特殊类 子类 则通过附加属性和方法来进行实现的扩展聚合通过创建一个聚合了其它对象的对象 从而获得新功能通过将功能委托给所聚合的一个对象 从而实现新功能 继承与聚合 例子 classStackextendsArrayList privateintstack pointer 0 publicvoidpush Objectarticle add stack pointer article publicObjectpop returnremove stack pointer publicvoidpush many Object articles for inti 0 i articles length i push articles Stacka stack newStack a stack push 1 a stack push 2 a stack clear 继承与聚合 继承优点容易进行新的实现 因为其大多数可继承而来易于修改或扩展那些被复用的实现聚合破坏了封装性 因为这会将父类的实现细节暴露给子类 白盒 复用 因为父类的内部细节对于子类而言通常是可见的当父类的实现更改时 子类也不得不会随之更改从父类继承来的实现将不能在运行期间进行改变 继承与聚合 聚合优点 黑盒 复用 因为被包含对象的内部细节对外是不可见封装性好实现上的相互依赖性比较小每一个类只专注于一项任务 通过获取指向其它的具有相同类型的对象引用 可以在运行期间动态地定义 对象的 聚合类 子类 则通过附加属性和方法来进行实现的扩展缺点易于导致系统中的对象过多为了能将多个不同的对象作为组合块 compositionblock 来使用 必须仔细地对接口进行定义 继承与聚合 Coad规则仅当下列的所有标准被满足时 方可使用继承 1 子类表达了 是一个 的特殊类型 而非 是一个由 所扮演的角色 2 子类的一个实例永远不需要转化 transmute 为其它类的一个对象 3 子类是对其父类的职责 responsibility 进行扩展 而非重写或废除 4 子类没有对那些仅作为一个工具类 utilityclass 的功能进行扩展 5 对于一个位于实际的问题域 ProblemDomain 的类而言 其子类特指一种角色 role 交易 transaction 或设备 device 继承与聚合 例 1 是一个 的特殊类型 而非 是一个由 所扮演的角色 失败 乘客是人所扮演的一种角色 代理人亦然 2 永远不需要转化 失败 随着时间的发展 一个Person的子类实例可能会从Passenger转变成Agent 再到AgentPassenger 3 扩展 而非重写和废除 通过 4 不要扩展一个工具类 通过 5 在问题域内 特指一种角色 交易或设备 失败 Person不是一种角色 交易或设备 继承并非适用于此处 继承与聚合 例 1 是一个 的特殊类型 而非 是一个由 所扮演的角色 通过 乘客和代理人都是特殊类型的人所扮演的角色 2 永远不需要转化 通过 一个Passenger对象将保持不变 Agent对象亦然 3 扩展 而非重写和废除 通过 4 不要扩展一个工具类 通过 5 在问题域内 特指一种角色 交易或设备 通过 PersonRole是一种类型的角色 继承适用于此处 继承与聚合 例 1 是一个 的特殊类型 而非 是一个由 所扮演的角色 通过 预订和购买都是一种特殊类型的交易 2 永远不需要转化 通过 一个Reservation对象将保持不变 Purchase对象亦然 3 扩展 而非重写和废除 通过 4 不要扩展一个工具类 通过 5 在问题域内 特指一种角色 交易或设备 通过 是一种交易 继承适用于此处 继承与聚合 小结1 聚合与继承都是重要的重用方法2 在OO开发的早期 继承被过度地使用3 随着时间的发展 我们发现优先使用聚合可以获得重用性与简单性更佳的设计4 当然可以通过继承 以增加可复合的类 enlargethesetofcomposableclasses 5 因此聚合与继承可以一起工作6 但是我们的基本法则是 优先使用对象聚合 而非 类 继承 区分接口继承与实现继承 深入分析继承机制 会发现它由两个可分的部分组成 函数接口的继承函数实现的继承作为类的设计者有时希望派生类只继承成员函数的接口 声明 有时希望派生类同时继承函数的接口和实现 但允许派生类改写实现有时则希望同时继承接口和实现 并且不允许派生类改写任何东西 区分接口继承与实现继承 例 abstractclassShape publicabstractvoiddraw virtualvoiderror Stringmsg intobjectID classRectangleextendsShape classEllipseextendsShape 区分接口继承与实现继承 定义纯虚函数的目的在于 使派生类仅仅只是继承函数的接口声明简单虚函数的目的在于 使派生类继承函数的接口和缺省实现非虚成员函数表明了一种特殊性上的不变性 因为它表示的是不会改变的行为 区分接口继承与实现继承 Tips 如果需要简单虚函数 不应将其声明为公有的决不要重新定义继承而来的非虚函数在C 中 如果要使用实现继承 尽可能使用private继承面向接口编程接口表达了对象在交互中的 角色 应该尽可能的避免实现继承 JamsGosling实现继承打破了类的封装实现继承增加了耦合避免 向下转换 继承层次 类型系统 类型一组值作用于这些值上的操作在OO世界中 类型 Type 类 Class 类型系统一组禁止误用值的规则类型表达式 定型断言 定型规则 类型检查算法可以在运行时检查 动态类型系统 也可在编译时检查 静态类型系统 类型系统 动态类型系统编译快 编译器实现简单程序员修改方便支持Test Modify方式最终仍可以发现错误静态类型系统编译仍相当快运行性能高可以找出拼写错误程序自描述性较好 多态性 多态性 polymorphism 多态变量 一个值在不同上下文中表示不同类型可以把多态变量看作是一个占位符多态消息 一个消息不同上下文中有不同的行为 实现 为限制对 多种类型 的滥用 需要使用继承来附加约束仅允许将子类型对象的类型 改变 为父类型 多态是和继承密切相关的 正因为有继承 才会有多态出现 多态从字面上的意思应该是多种形态 更进一步 延伸到继承里来 那么多态就应该是具有相同的操作不同的行为的一种特征 多态性 多态性 问题为什么要引入多态 为了支持对类型扩展中涉及的行为扩展 早期的想法现在呢 多态性 多态的应用代替分支语句使得不同的行为 实现 可以由相同的消息 接口 来引发 以提供更利于重用的封装留下 扩展点 便于今后进行扩展代替 函数指针 向上转型 upcasting publicclassShape voiddraw staticvoidstart Shapes s draw publicstaticvoidmain String agrs start newCircle start newSquare classCircleextendsShape voiddraw System out println drawCircle classSquareextendsShape voiddraw System out println drawSquare 向上转型 upcasting 在start 方法中 通过传入的参数类型不同 表现出来的行为也会不同 但是传入后的参数都统一转型为Shape这个基类型 这里就表现为向上转型 由导出类到基类 从继承图上面我们可以看出是向上移动的 因此我们一般称之为 向上转型 向上转型是从一个较具体的类型转换为一个较抽象的类型的过程 所以说是安全的 在导出类中至少包含了基类的方法 在向上转型的过程中 由于在导出类中可能含有基类中没有的方法 类接口会丢失一些方法 将一个方法调用同一个方法主体关联起来被称之为绑定 若在程序执行前绑定就被称为早期绑定 晚期绑定也被称为动态绑定 即编译器始终都不会知道对象的类型 只有当方法在运行期间被调用时 方法的调用机制根据实参类型找到正确的方法体 动态绑定 动态绑定 动态绑定 运行时将消息关联到实现代码上处理多态的机制 真正的多态 多态性规则 总是使用尽可能高的抽象级别来编程总是把字段 局部变量 方法参数的类型声明为继承层次中最高的类 构造器中多态方法的行为 publicclassShape3 Shape3 System out println thisisashape draw voiddraw publicstaticvoidmain St

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论