chp5_1

Similar documents
OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

软件工程文档编制

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

模板

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

无类继承.key

OOP with Java 通知 Project 3: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Chapter 9: Objects and Classes

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

Microsoft Word - 新1-12.doc

Microsoft Word - 第5章.doc

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

<4D F736F F F696E74202D C DB5DA3131D5C25FBCCCB3D0BACDB6E0CCAC2E BBCE6C8DDC4A3CABD5D>

javaexample-02.pdf

<4D F736F F F696E74202D20B5DA3035D5C220C3E6CFF2B6D4CFF3B8DFBCB6B3CCD0F2C9E8BCC6>

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

Strings

chp4

Microsoft Word - 第3章.doc

OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢

Microsoft PowerPoint - 07 派生数据类型

Microsoft Word - 第2章.doc

Microsoft Word - 第5章.doc

教案模板4-2

Microsoft Word - 第5章.doc

Microsoft Word - word模板-教师.doc

PowerPoint Presentation

Guava学习之Resources

untitled


OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

Microsoft PowerPoint - 04-Inheritance.ppt

幻灯片 1

《计算概论》课程 第十九讲 C 程序设计语言应用

Microsoft PowerPoint - L17_Inheritance_v4.pptx

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

Microsoft Word - chap10.doc

Microsoft Word - JCS5.doc

何对象存在, 所以, 如果不将它设置为类相关的, 则没有办法得到任何的对象, 也就无法调用这个 main() 方法 知识准备 :static 变量的引用方法 1. 通过对象定位变量 在 节中我们定义了 StaticTest 类, 并在类中定义了 static 变量 现在我们通

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc

教学内容 1 2 类和对象 Java 面向对象特性

<4D F736F F F696E74202D20A1B64A617661B8DFBCB6BCBCCAF5A1B7B5DA31312E35BDB220B6AFCCACC0E0D0CDBCECB2E92E707074>

2009年3月全国计算机等级考试二级Java语言程序设计笔试试题

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

博学谷 让 IT 教学更简单, 让 IT 学习更有效 第五章补充案例 案例 5-1 声明类 一 案例描述 1 考核知识点类的声明 2 练习目标 掌握声明一个类的语法格式 掌握如何在类中声明成员变量和成员方法 3 需求分析在程序中, 设计一个表示学生的类, 该类具有以下属性和方法 : 该类具有表示姓名

Microsoft Word - 物件導向編程精要.doc

JavaIO.PDF

Microsoft PowerPoint - 第06讲_继承.ppt [兼容模式]

《大话设计模式》第一章

EJB-Programming-4-cn.doc

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

拦截器(Interceptor)的学习

PowerPoint Template

Microsoft Word - ch04三校.doc

<4D F736F F D204A617661B3CCD0F2C9E8BCC6CFB0CCE2D3EBCAB5D1B5BDCCB3CC20B5DA33D5C22E646F63>

Strings

Microsoft Word - 正文.doc

<4D F736F F D204A617661B3CCD0F2C9E8BCC6D3EBCAB5BCF9BDCCB3CCA3A8B5DA32B0E6A3A920B5DA35D5C22E646F63>

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

Java

Microsoft Word - Hibernate与Struts2和Spring组合指导.doc

Microsoft Word - 第3章.doc

Struts2自定义类型转换.doc

第1章 Delphi简介

Microsoft Word - 第3章.doc

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

EJB-Programming-3.PDF

试卷代号 : 座位号 中央广播电视大学 学年度第一学期 " 开放本科 " 期末考试 面向对象程序设计 ( 本 ) 试题 2011 年 1 月 题号 一 一 一四总分 一 分数 得分 评卷人 - 单选题, 在括号内填写正确的选项编号 { 每小题 2 分, 共

Microsoft Word - 01.DOC

chp6.ppt

<4D F736F F F696E74202D20B5DA39D5C220C3E6CFF2B6D4CFF3D3EFD1D4B5C4B1E0D2EB2E BBCE6C8DDC4A3CABD5D>

Microsoft PowerPoint - CPP-Ch Print.ppt [兼容模式]

建模与图形思考

untitled

C++_Lecture

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple

java2d-4.PDF

<4D F736F F D20B5DA32D5C220C3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6B3F5B2BD2E646F6378>

Microsoft PowerPoint - ch12 [Compatibility Mode]

Microsoft Word - 新正文.doc

运算符重载 为什么要 运算符重载 那些运算符可以重载, 哪些不可以 如何实现运算符重载 实现方式 : 成员函数与非成员函数 类型转换 怎样实现对象与基本数据类型数据的运算 2

Stateless Session Beans(无状态bean)的学习

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

AVEVA PMLNet Guide

在Spring中使用Kafka:Producer篇

设计模式 Design Patterns

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas

ASP.NET实现下拉框二级联动组件

Adobe® Flash® 的 Adobe® ActionScript® 3.0 程式設計

Transcription:

Java 软件设计基础 5. 继承与多态

类的封装 类的特性 Java 程序设计的基本单位是类, 类是用来创建具体对象的模板, 有以下三个重要特性 : 封装 Java 语言中, 对象就是对一组变量和相关方法的封装 (Encapsulation), 通过对对象的封装, 实现模块化和信息隐藏 通过对类的成员辅以一定的访问限制, 实现类中成员的信息隐藏 继承 继承 (inheritance) 允许创建分等级层次的类, 在 Java 中, 所有的类都是直接或间接的继承 java.lang.object 得到的 多态 多态 (Polymorphism) 是指同名的不同方法在类程序中共存, 系统根据传递参数个数或类型的不同来决定调用哪一个方法

类的封装 封装是将代码及其处理的数据绑定在一起的一种编程机制, 该机制保证了程序和数据不受外部干扰且不易被误用 利用抽象数据类型将数据和基于数据的操作结合在一起, 数据被保护在抽象数据类型的内部, 系统的其他部分只有通过包裹在数据之外被授权的操作, 才能够与这个抽象数据类型进行交互 类是 Java 封装的基本单元 一个类定义了将被一个对象集共享的结构和行为 ; 每一个给定的对象都包含这个类定义的数据和操作 ; 对象也被看成是类的实例 (instance of a class); 类是逻辑结构, 而对象是真正存在的物理实体 封装可以提高程序中数据的完整性和安全性 ; 开发过程的复杂性 ; 减少出错可能 ; 提高类或模块的可重用性

访问权限 类中的每个方法或成员变量的访问权限都可以通过修饰符 (public private protected default) 被标记 这种访问权限控制实现了一定范围内的信息隐藏 private 被修饰的成员变量和方法称为私有变量和私有方法 类中限定为 private 的成员变量和方法只能被这个类本身的方法访问, 不能在类外通过名字来访问 Xx has private access in A Xy( ) has private access in A

对于私有成员变量和方法, 只有在本类中创建该类的对象时, 这个对象才能访问自己的私有变量和类中的私有方法 私有变量和方法 class Temp{ private int books; Temp(){ books=15; private int getnum(){ return books; public static void main(string args[]){ Temp t1=new Temp(); t1.books=30; int m=t1.getnum(); System.out.println("books="+m); 在类内部创建对象, 可以访问自己的私有变量和私有方法 同一个类的不同对象可以访问对方的私有变量或调用对方的私有方法, 这是因为访问保护是控制在类的级别上, 而不是对象的级别上

构造方法也可以限定为 private, 如果一个类的构造方法被声明为私有, 则其他类不能生成该类的一个对象 X 编译报错 protected 类中限定为 protected 的成员可以被这个类本身引用, 被它的子类以及同一个包中所有其他的类访问

public 修饰的成员变量和方法被称为公共变量和公共方法, 可被所有的类访问 public 方法的作用是让类的客户了解类提供的服务, 即类的公共接口, 而不必关心类是如何完成任务的 friendly 这是缺省情况, 限定为友好的成员可以被这个类本身和同一个包中的其他类访问, 但是对于包外的所有类就不能访问

5.2 类的继承 继承机制 继承是面向对象编程技术的一块基石 继承能够创建一个通用类, 并定义一系列相关项目的一般特性 该类可以被更具体的类继承 每个具体的类都增加一些自己特有的东西 继承是一个对象获得另一个对象的属性的过程 由继承得到的类为子类 (subclass 或 childclass), 也被称为派生类 (derived class) 扩展类 (extended class) 被继承的类为超类 (superclass), 也被称为基类 (base class) 或者父类 (parent class), 包括所有直接或间接被继承的类 ; 类可以从另一个类的子类的子类的子类 继承而来, 最终都是继承自最顶级的类 Object 定义在 Object 中的方法可被所有子类使用

Java 平台类层次结构 : 所有类都是 Object 类的后裔 Object ImaginaryNumber 的间接父类 Number ImaginaryNumber 的直接父类 ImaginaryNumber

继承支持按层次分类的概念 简单的说, 类的继承性就是新的子类可以从另一个父类派生出来, 并自动拥有父类的全部属性和方法 子类继承父类的成员变量与方法, 就如同在子类中直接声明的一样, 可以被子类中自己声明的任何实例方法所调用 子类继承父类的状态和行为, 同时也可以修改继承自父类的状态和行为, 并添加新的状态和行为 通俗的说法 : 子类更具有特殊性 继承用来为 is-a 关系建模 不要为了重用方法而盲目的派生一个类 例如, 从 Person 类派生 Tree 类毫无意义 子类和父类之间必须存在 is-a 关系 单继承 使得代码更加可靠, 不会出现因多个父类有相同的方法或属性所带来的麻烦

按层次分类 继承父类的属性与方法 添加新的特性 ( 包括新的属性与方法 )

创建子类 格式 说明 [ 修饰符 ] class 子类名 extends 父类名 { 类体 子类能够继承父类中 public 和 protected 成员变量和方法 ; 如果子类和父类在同一个包内, 子类能继承父类中用默认修饰符修饰的成员变量和方法 ; 一般情况下, 子类不能继承父类中的 private 成员变量和方法 ; 这里要特别说明的是, 因为嵌套类可以访问其外部类的所有私有成员, 所以, 若子类是继承自某公共或者受保护嵌套类, 则可以间接访问 ( 关于嵌套类, 我们将在下节课中讲解 ) 若缺省 extends 子句, 则该类为 java.lang.object 的子类

Xc has private access in SuperClass

如果子类声明了一个与父类中的成员同名的成员, 则子类不继承父类中的同名成员 ; 以上程序将打印 5, 表明子类 Sub 中并未继承父类的 a

构造方法 与属性和方法不同, 父类的构造方法并不传给子类, 它们只能从子类的构造方法中通过关键字 super 调用 调用父类的构造方法必须使用关键字 super, 并且这个调用必须是构造方法的第一条语句 在子类中使用父类构造方法的名字会引起语法错误 构造方法链 在任何情况下, 构造一个类的实例时, 将会沿着继承链调用所有父类的构造方法, 父类的构造方法在子类的构造方法之前调用

构造方法链例程 public class Faculty extends Employee{ public static void main(string args[]){ new Faculty(); public Faculty(){ System.out.println(" 类 Faculty 的无参构造方法 "); class Employee extends Person{ public Employee(){ System.out.println(" 类 Employee 的无参构造方法 "); class Person{ public Person(){ System.out.println(" 类 Person 的无参构造方法 ");

关键字 super Java 中通过 super 来实现对父类成员的访问,super 用来引用父类中的方法和变量, 主要是用于继承被隐藏 (hiding) 的成员变量或者被覆盖的方法 使用情况 访问父类被隐藏的成员变量, 其引用格式为 : super. 成员变量名 调用父类被覆盖的方法, 其引用格式为 : super. 方法名 ([ 参数列表 ]) 调用父类的构造方法, 其引用格式为 : super([ 参数列表 ])

例程 : 自行车类 自行车类作为父类 三个属性 : 踏板步调 速度 档位 构造方法 提供四个方法 : 设置踏板步调 ; 设置档位 ; 刹车减速 ; 提速 ; 父类 Bicycle public class Bicycle{ public int cadence; public int speed; public int gear; public Bicycle(int sc,int ss,int sg){ gear=sg; speed=ss; cadence=sc; public void setcadence(int newvalue){ cadence=newvalue; public void setgear(int newvalue){ gear=newvalue; public void applybrake(int decrement){ speed-=decrement; public void speedup(int increment){ speed+=increment;

自行车下面还有许多子类, 如山地车 公路自行车等 以山地车为例 除了拥有父类的三个属性, 还有座高这一特有的属性 新增的方法 : 设置座高

构造方法也可以利用 super 关键字, 改为 :

this 与 super 的总结 this 用来引用当前对象,super 用来引用当前父类对象 用 this 和 super 区别分别出现在父类 子类中的同名成员变量和类中方法使用的同名局部变量 子类隐藏了父类的成员变量 子类的方法遮蔽了子类的成员变量

this 的使用 可以出现在实例方法和构造方法中, 但不可以出现在类方法中 因为类方法可以直接通过类名直接调用, 这时可能还没有任何对象诞生 this 可以出现在类的构造方法中, 代表使用该构造方法创建的对象 代表创建的对象 exa, 这时 number 还未赋值 ; number 赋值完毕 ;

this 可以出现在类的实例方法中, 代表使用该方法的当前对象 类的实例方法可以通过 this 调用该类的其他方法, 或者成员变量 实例方法中的 this class A{ int x; void f(int x){ this.x=x; this.g(); void g(){ this.x++; 在某个对象调用 f 方法的过程中又调用了方法 g 由于这种逻辑关系非常明确, 所以当一个方法调用另一个方法时可以省略 this, 即本条语句等价于 : g();

super 的使用 用来访问父类被隐藏的成员变量, 或调用父类被覆盖的方法和构造函数 父类 class Point{ protected int x,y; public Point(){ x=0; y=0; System.out.println( 点的构建 +this.tostring()); public Point(int a,int b){ x=a; y=b; System.out.println( 点的构建 +this.tostring()); public String tostring(){ return [ +x+, +y+ ] ;

主方法部分 public static void main(string args[]){ Circle circle1=new Circle(); Circle circle2=new Circle(3,4,5);

例程 : 成员变量的隐藏和方法的覆盖 父类的成员变量 父类的构造函数 父类的方法

子类 class SubClass extends SuperClass{ int x; SubClass(){ x=5; System.out.println( in SubClass:x= +x); void dosomething(){ super.dosomething(); System.out.println( in SubClass.doSomething() ); System.out.println( super.x= +super.x+ ;sub.x= +x); 子类的成员变量隐藏了父类的成员变量 子类的方法覆盖了父类的方法 子类的方法中调用了父类的方法

分析 : 根据构造方法链的原理, 子类在实例化时, 首先调用父类构造函数, 实例化父类 之后才是子类自身实例化» 这就是为什么上例中会首先打印 in SuperClass:x=3 的原因 将程序片段略作修改 :

当运行主程序的 SubClass sub=new SubClass(); 语句时, 上述程序会报错, 原因在于子类实例化之前要实例化父类, 调用父类中的无参数构造方法, 而父类中不存在无参数构造方法 那么, 父类中为什么会不存在无参数的构造方法呢?» 当构造一个类的对象时, 编译器首先判断类是否有构造方法, 如果没有, 则自动加上一个默认构造方法 ; 而一旦发现有构造方法后, 则不再自动加上构造方法» 此时再用无参数的构造方法去创建对象, 就会提示出错, 因为已经没有系统提供的默认构造方法了 如果一个类要生成其他子类, 最好提供一个无参数的构造方法以避免编程错误

在上述程序中, 除了在父类中另外再定义一个无参数构造方法外, 还可以显式的调用父类的构造函数, 使用 super 语句 但是这一语句必须是子类构造函数的第一句» 改写如下 :

总结 继承的最大好处就是类的可重用性 当创建自己的类时, 应尽可能将它作为某一个类的子类, 在自己的子类中加入一些特殊的内容, 而不必重新定义这个类所需的全部属性和行为 初始化过程总是由高级到低级层次 ; 资源回收过程应从低级到高级层次进行

5.3 多态机制 多态 又被称为 一个方法名字, 多个行为结果 通过方法覆盖 (Override) 和方法重载 (Overload) 来实现多态 方法重载 一个类中可以有多个具有相同名字的方法, 由传递给它们的不同个数和类型的参数来决定使用哪种方法 通过重载可以定义同类的操作方法 ( 行为 ), 而不需要取很多个类似又容易混淆的名字 方法的重载是功能多态性的体现 功能多态性是指可以向功能传递不同的消息, 以便让对象根据相应的消息来产生一定的行为

重载方法需要满足以下条件 : 方法名相同 ; 方法的参数签名 ( 即参数类型 个数 顺序 ) 不相同 ; 方法的返回类型可以不相同, 方法的修饰符也可以不相同 ; 不能根据方法返回类型的不同来区分重载的方法

例程 : 希望根据接收到的不同数据作出不同的反应 根据不同的参数类型 个数 顺序进行判断, 决定到底执行哪个方法

方法覆盖 如果子类中实例方法的参数签名和返回类型与父类中的实例方法都一样, 就称为子类中的方法覆盖了父类的方法 通过方法覆盖, 子类可以重新实现父类的某些实例方法, 使其具有自己的特征 覆盖方法也可以返回被覆盖方法的返回类型的子类型, 称为协变返回类型 (convariantreturn type) 在方法覆盖中, 子类需要保持与父类完全一致的方法头声明, 否则就不是方法覆盖 有以下情况 : 参数个数 类型 顺序与父类完全相同, 而返回类型类型不同 :

方法的覆盖 public class Example{ public static void main(string args[]){ B b=new B(); double d=b.area(); class A{ protected int x=10,y=12; public int area(){ return x*y; class B extends A{ public double area(){ return 3.14*x*y/4; Xarea() in B cannot override area() in A; attempting to use incompatible return type

参数个数或参数类型与父类不尽相同, 这时子类出现两个方法具有相同的名字, 但保证了参数的不同, 即子类出现了重载的方法 : 方法的覆盖 public class Example{ public static void main(string args[]){ B b=new B(); double d=b.area(12); System.out.println(d); class A{ protected int r=10; public double area(){ return r*r; class B extends A{ public double area(){ return 3.14*r*r/4; public double area(int x){ return 3.14*r*x/4; 合法覆盖父类的方法后, 可以合法的定义另外的重载方法

子类方法缩小了父类方法的访问权限 : 方法的覆盖 public class Example{ public static void main(string args[]){ B b=new B(); double d=b.area(); System.out.println(d); class A{ protected int r=10; public double area(){ return r*r; class B extends A{ protected double area(){ return 3.14*r*r; Xarea() in B cannot override area() in A; attempting to assign weaker access privileges was public

方法的隐藏 如果子类定义的类方法的签名和父类中方法的签名相同, 那么子类中的方法就隐藏了超类中的方法 父类的静态方法不可以被子类隐藏为非静态, 父类中的非静态方法不可以被子类覆盖为静态 终止覆盖 为了防止利用属于系统重要信息的类来创建子类和进行方法覆盖, 替换原有的类攻击系统, 防止父类被覆盖, 引入了仲只覆盖的理念, 即 final 修饰符外延性的使用 用 final 修饰类来避免产生子类, 用 final 修饰符修饰父类中的方法就可以避免子类来覆盖此方法 父类的私有方法是隐性 final 的, 不能被子类覆盖

5.4 tostring 方法 Java 中的每个类都源于 java.lang.object 类 如果一个类在定义时没有指定继承, 它的父类默认是 Object tostring() 方法 调用对象的 tostring() 方法返回一个代表该对象的字符串 默认情况下, 返回一个由该对象所属的类名 @ 和该对象十六进制的散列码组成的字符串

通常应该覆盖 tostring() 方法, 使它返回一个代表该对象的易懂的字符串 也可以传递对象来调用 : System.out.println(object) System.out.print(object) 这等价于调用 : System.out.println(object.toString()) System.out.print(object.toString())

5.5 抽象类 引言 在继承的层次结构中, 随着各新子类的出现, 类变得越来越专门和具体 类的设计应该保证父类包含子类的共同特征, 有时, 将一个父类设计的非常抽象, 以至于它没有具体的实例, 这样的类称为抽象类 (abstract class) 说明 抽象类和常规类一样具有数据和方法, 但是不能用 new 操作符来创建它的实例 ; 抽象方法只有方法头而没有实现, 它的实现由子类提供 子类可以是抽象的, 即使它的父类是具体的

非抽象类不能包含抽象方法, 如果一个抽象父类的子类不能实现所有的抽象方法, 它必须声明为抽象的 抽象类不能用 new 操作符实例化, 但仍然可以定义它的构造方法, 可在子类的构造方法中调用 包含抽象方法的类必须是抽象的 但是允许声明没有抽象方法的抽象类

例 有以下形状类 : 形状类 public class Shape{ private String color = white ; public String getcolor(){ return color; public void setcolor(string color){ this.color=color; public double getarea(){ public double getperimeter(){

当涉及计算面积及周长时, 其方法的实现取决于几何对象的具体类型 当然, 可也以将所有的形状归为一类, 以方法的重载来计算形状的面积及周长, 但这样使得类的特征不够明显 可将 getarea 和 getperimeter 方法定义为抽象方法, 这些方法将在子类中实现 形状类 public abstract class Shape{ private String color = white ; public String getcolor(){ return color; public void setcolor(string color){ this.color=color; public abstract double getarea(); public abstract double getperimeter();

子类继承抽象父类, 增加自己特有的属性, 并实现抽象父类的抽象方法

具体实例的创建 创建了一个新的圆形与新的矩形, 并把它们赋值给变量 s1 和 s2, 这两个变量的类型是 Shape 当使用 s1.getarea() 时, 由于 s1 是一个圆形, 因此会自动调用 Circle 类中实现的 getarea 方法 调用哪个方法由 JVM 在运行时根据对象的类型动态的决定

类型转换 (cast) 分析 从以上语句可看出 mybike 属于 MountainBike 类型 MountainBike 是从 Bicycle 和 Object 派生而来, 因此 MountainBike 是 Bicycle, 也是 Object, 可以在任何能够调用 Bicycle 和 Object 对象的位置使用它 相反的情况并不一定成立 :Bicycle 可能是 MountainBike, 但并不一定是,Object 可能是 Bicycle 或者 MountainBike, 但并不一定是 类型转换允许在一种类型的位置上使用另一种类型的对象, 但是只能在继承和实现允许转换的对象之间进行 类型转换有两种 :

隐式类型转换 (implicit cast), 如 : 语句中的 obj 既是 Object 也是 MountainBike 显式类型转换 (explicit cast) 以上语句会出现编译时错误, 因为编译器不知道 obj 是 MountainBike 类, 此时需要通过显式类型转换, 将 MountainBike 赋值给 obj: 这种类型转换插入一个运行时的类型检查, 如果 obj 不是 MountainBike, 就会抛出异常

5.6 接口 接口的特点 对象通过暴露的方法定义它们和外部世界的交互 方法形成对象和外部世界的接口 (interface) 接口通常是一组具有空方法体的相关方法 通过实现接口, 类可以更加正式的说明它承诺提供的行为 接口构成了类和外部世界之间的契约, 并且该契约在编译时由编译器强制实施 如果类声明实现一个接口, 那么这个接口定义的所有方法都必须出现在其源代码中, 否则就不能成功编译 接口不是类层次结构的一部分, 但它们与类结合在一起工作 Java 通过接口使得处于不同层次 甚至互不相关的类可以具有相同的行为 ( 即实现相同的接口 )

接口的定义 格式 : Java 中接口是类似于类的一种引用类型, 只能包含常量 方法体和嵌套类型, 其中没有方法体 ; 接口不能被实例化, 只能被类实现, 或者被其他接口扩展 说明 关键字 interface 表明其后紧跟着的是接口名 ; extends 表明继承自那些父接口 ;

访问权限控制符 public 表明任意类和接口均可使用这个接口 ; 缺省修饰符表明只有与该接口定义在同一个包中的类和接口才可以使用这个接口 接口体 常量定义 : 在接口中定义的常量被缺省默认为 public final static, 而不需特意写明以上修饰符, 也不能被其他修饰符修饰 方法体 : 接口中只进行方法的声明, 而不负责方法的实现, 因此没有方法体 定义在接口中的方法被默认为 public 和 abstract, 同样不需特意修饰, 也不能被其他修饰符修饰 接口的特点 接口可以继承自多个父接口 ; 如果在子接口中定义了和父接口同名的常量, 则父接口中的常量被隐藏 ; 如果在子接口中定义了和父接口同名的方法, 则父接口中的方法被重载 ;

接口允许没有父接口 ; 接口的实现 实现格式 说明 类修饰符只能是 public 或缺省 ; 如果实现某个接口的类不是抽象类或者该抽象类的子类, 则都必须实现指定接口的所有抽象方法, 抽象方法在使显示要修饰为 public, 并且要求方法的参数列表 名字和返回类型与接口定义中的完全一致

例程 定义接口 Shape2D, 指明类需要实现的方法 : 计算二维图形的面积和周长 构造两种二维图形的类 : 矩形类和圆形类, 实现该 Shape2D 接口

抽象类和接口都可以用于模拟共同特征, 一般来说 strong is-a relationship 应该用类来继承模拟 ;weak is-a relationship 是类属关系, 指对象拥有某种属性, 可用接口来模拟 例如, 职员和人的关系应该用类继承模拟 ; 字符串都可以用来比较, 则可以使 String 类实现 Caparable 接口 可以使用接口避开单重继承的限制

5.7 包 包 (package) 是组织一组相关类和接口的名称空间 包的分类 : API Java 平台提供的数量庞大的类库 ( 包的集合 ), 可以用于应用程序的开发, 它的包代表和通用编程相关的最常见的任务 API 使得程序员可以把精力集中于特定的应用程序设计, 而不必在基础设施上浪费时间 自定义包 Java 编程语言编写的软件可能由数百或甚至数千个独立的类构成, 把相关的类和接口存放在包中以组织这些内容 包的作用 如同文件夹的概念一样, 不同的包中的类可以同名, 这样可以避免命名的冲突 ; 使得功能相关的类易于查找和使用, 同一包中的类和接口通常是功能相关的 ;

定义 可提供一种访问权限的控制机制, 一些访问权限以包为访问范围 包是一组相关类和接口的集合, 即类和接口的容器 它提供了访问权限 ( 控制类之间的访问 ) 和命名的管理机制 ( 划分类名空间 ) 包层次的根目录是由环境变量 CLASSPATH 来确定的 定义格式 说明 : package 包名 1[. 包名 2[. 包名 3 ]]; 在定义类和接口的源文件的第一行使用 package 语句, 就指明了该文件中定义的类和接口属于第一条语句定义的包 ; 包可以带路径, 形成与 Java 开发系统文件结构相同的层次关系

包的定义 package Family; class Father{ class Mother{ class Son{ 依次把 Father 类 Mother 类 Son 类装入包 Family 不同程序文件内的类也可同属于一个包, 只要在这些程序文件前加上同一个包的声明 ; 包的引用 如果缺省 package 语句, 则指定为无名包 将类和接口组织成包的目的是为了能够更有效的使用包中的已经具备一定功能的类

格式 import 包名 1[. 包名 2[. 包名 3 ]]. 类名 *; 装载使用已编译好的包的方式 : 在要引用的类名前带上包名 : 在文件开头使用 import 引入包中的类 : 在文件前使用 import 引入包中所有的类 : 装载方式 2 import Animals.*; class Check{ Cat cat=new Cat(); Dog dog=new Dog();

说明 使用 * 时表示要从包中引入所有的类, 也只能是该包中的类 ; Java 编译器为所有程序自动引入包 java.lang, 所以不必显式引入 ; 需要注意的是 : 包实际上并不如同最初看上去那样具有层次结构, 某个包名字中的. 并不表示它们之间的包含关系, 只是为了使它们之间的联系更明显» 以上语句只能导入 java.awt 包中的所有类, 而不能导入 java.awt.font java.awt.color 或者任何 java.awt.xxxx 包, 如果计划使用以上的包, 则必须另外导入 :