Programming in JAVA 第7章 类的继承性(下) 接口与多态.

Slides:



Advertisements
Similar presentations
系統分析與設計 楊子青 H-1 H 、物件導向技術 n 物件導向的基本概念 – 物件、類別 – 封裝、繼承 – 同名異式 ( 多型 ) 、超荷 ( 過載 ) n 物件導向分析與設計及塑模工具 n UML 塑模工具.
Advertisements

第四章 类、对象和接口.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
项目6 通用堆栈.
四資二甲 第三週作業 物件導向程式設計.
面向对象的程序设计(一).
第一章 面向对象程序设计.
第二章 JAVA语言基础.
類別的繼承-一般關係: 繼承是宣告的類別繼承現存類別的部份或全部的成員資料和方法 , 新增額外的成員資料和方法或覆寫和隱藏繼承類別的方法
Ch07 介面與多重繼承 物件導向程式設計(II).
第14章 c++中的代码重用.
第10讲 Java面向对象编程基础(4) 教学目标 主要内容.
JAVA程序设计 (03) JAVA Programming
第5章 进一步讨论对象和类.
再回首: Java关键字 数据类型:byte boolean char double float int long short ,
第5章 Java中类、对象、接口 及包的概念 5.1 类的基本概念 5.2 类的继承概念 5.3 抽象类和接口 5.4 包.
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
Ch08 巢狀類別 物件導向程式設計(II).
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
H、物件導向技術 物件導向的基本概念 物件、類別 封裝、繼承 同名異式(多型) 、超荷(過載) 物件導向分析與設計及塑模工具 UML塑模工具.
Interfaces and Packages
EBNF 请用扩展的 BNF 描述 C语言里语句的结构; 请用扩展的 BNF 描述 C++语言里类声明的结构;
Classes Lecturer: 曾學文.
第六章 类的扩展与继承.
程式敘述執行順序的轉移 控制與重複、方法 Lecturer:曾學文.
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
Ch10 類別與物件-方法 Java程式設計(2).
程式設計實作.
Java软件设计基础 5. 继承与多态.
Java程序设计 第9章 继承和多态.
辅导课程六.
類別的繼承 Vehicle Car.
中国矿大计算机学院杨东平 第5章 接口和包 中国矿大计算机学院杨东平
2019/1/16 Java语言程序设计-类与对象 教师:段鹏飞.
Php class 組員: 賴羿陵 林昱廷 莊正暉 張雅晴
Java程序设计 第2章 基本数据类型及操作.
第5讲 使用类和对象编程(三) 内部类 实例 程序控制结构 选择语句.
C/C++/Java 哪些值不是头等程序对象
第七章 操作符重载 胡昊 南京大学计算机系软件所.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
Java程序设计 第10章 抽象类和接口.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
第二章 Java基本语法 讲师:复凡.
$9 泛型基础.
C++复习3 ----类的继承与派生.
C#面向对象程序设计 $6 深入理解类.
第二章 Java基本语法 讲师:复凡.
Interfaces and Packages
本节内容 类成员的访问控制 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
第二章 Java语法基础.
3.16 枚举算法及其程序实现 ——数组的作用.
Chapter 18 使用GRASP的对象设计示例.
多层循环 Private Sub Command1_Click() Dim i As Integer, j As Integer
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
辅导课程十五.
第二章 Java基本语法 讲师:复凡.
方法進階及物件導向基礎 Lecturer: 楊昌樺.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
基于列存储的RDF数据管理 朱敏
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
第二章 Java基础语法 北京传智播客教育
第二章 Java基本语法 讲师:复凡.
第6章 继承和多态 伍孝金
Presentation transcript:

Programming in JAVA 第7章 类的继承性(下) 接口与多态

目录 7.1 接口 7.2 塑型 7.3 多态的概念 7.4 多态的应用 7.5 构造方法与多态 7.6 内部类 7.7 本章小结

7.1 接口 接口 与抽象类一样都是定义多个类的共同属性 使抽象的概念更深入了一层,是一个“纯”抽象类,它只提供一种形式,并不提供实现 允许创建者规定方法的基本形式:方法名、自变量列表以及返回类型,但不规定方法主体 也可以包含基本数据类型的数据成员,但它们都默认为static和final

7.1.1 接口的作用及语法 接口的作用 接口 是面向对象的一个重要机制 实现多继承,同时免除C++中的多继承那样的复杂性 建立类和类之间的“协议” 把类根据其实现的功能来分别代表,而不必顾虑它所在的类继承层次;这样可以最大限度地利用动态绑定,隐藏实现细节 实现不同类之间的常量共享

7.1.1 接口的作用及语法 ——与抽象类的不同 接口 接口允许我们在看起来不相干的对象之间定义共同行为

<<Interface>> 7.1.1 接口的作用及语法 ——例7_1 接口 保险公司的例子 具有车辆保险、人员保险、公司保险等多种保险业务,各种业务的保险对象不同,但在对外提供服务方面具有相似性,如都需要计算保险费(premium)等,因此可声明一个Insurable 接口,并使不同的类实现这个接口 在UML图中,实现接口用带有空三角形的虚线表示 <<Interface>> Insurable Company Person Car

7.1.1 接口的作用及语法 接口的语法 接口 使用关键字interface声明接口 声明格式为 [接口修饰符] interface 接口名称 [extends 父接口名]{ …//方法的原型声明或静态常量 } 接口的数据成员一定要赋初值,且此值将不能再更改,允许省略final关键字 接口中的方法必须是“抽象方法”,不能有方法体,允许省略public及abstract关键字

7.1.1 接口的作用及语法 ——例7_1保险接口的声明 Insurable 接口声明如下,其中的方法都是抽象方法 接口 7.1.1 接口的作用及语法 ——例7_1保险接口的声明 接口 Insurable 接口声明如下,其中的方法都是抽象方法 public interface Insurable { public int getNumber(); public int getCoverageAmount(); public double calculatePremium(); public Date getExpiryDate(); }

7.1.1 接口的作用及语法 ——例7_2 声明一个接口Shape2D,可利用它来实现二维的几何形状类Circle和Rectangle 接口 7.1.1 接口的作用及语法 ——例7_2 接口 声明一个接口Shape2D,可利用它来实现二维的几何形状类Circle和Rectangle 把计算面积的方法声明在接口里 pi值是常量,把它声明在接口的数据成员里 interface Shape2D{    //声明Shape2D接口 final double pi=3.14;   //数据成员一定要初始化 public abstract double area(); //抽象方法 } 在接口的声明中,允许省略一些关键字,也可声明如下 interface Shape2D{ double pi=3.14; double area();

7.1.2 实现接口 接口的实现 接口 接口不能用new运算符直接产生对象,必须利用其特性构造新的类,再用新类来创建对象 利用接口构造类的过程,称为接口的实现 使用implements关键字,语法如下 public class 类名称 implements 接口名称 { /* Bodies for the interface methods */ /* Own data and methods. */ } 必须实现接口中的所有抽象方法 来自接口的方法必须声明成public

7.1.2 实现接口 ——例7_3 接口 实现接口Insurable,声明汽车类实现例6.1中的Insurable接口,实现接口中的所有抽象方法 public class Car implements Insurable { public int getPolicyNumber() { // write code here } public double calculatePremium() { public Date getExpiryDate() { public int getCoverageAmount() { public int getMileage() { //新添加的方法 //write code here

7.1.2 实现接口 ——对象转型 接口 对象可以被转型为其所属类实现的接口类型 7.1.2 实现接口 ——对象转型 参看例子TestInsurable.java 注意: 文件名必须与带有main方法的那个类同名。 接口也是一种类,所以如果定义成为了public ,则在同一个文件中的其他类也不能定义成为public。 接口 对象可以被转型为其所属类实现的接口类型 getPolicyNumber、calculatePremium是Insurable接口中声明的方法 getMileage是Car类新添加的方法,Insurable接口中没有声明此方法 Car  jetta = new Car(); Insurable  item = (Insurable)jetta; //对象转型为接口类型 item.getPolicyNumber(); item.calculatePremium(); item.getMileage();        // 接口中没有声明此方法,不可以 jetta.getMileage();       // 类中有此方法,可以 ((Car)item).getMileage(); // 转型回原类,可调用此方法了

7.1.2 实现接口 ——例7_4 接口 声明Circle与Rectangle两个类实现Shape2D接口 { { 7.1.2 实现接口 ——例7_4 接口 声明Circle与Rectangle两个类实现Shape2D接口 class Circle implements Shape2D { double radius; public Circle(double r) radius=r; } public double area() return (pi * radius * radius); class Rectangle implements Shape2D { int width,height; public Rectangle(int w,int h) width=w; height=h; } public double area() return (width * height);

7.1.2 实现接口 ——例7_4运行结果 接口 测试类 运行结果 public class InterfaceTester { 7.1.2 实现接口 ——例7_4运行结果 接口 测试类 public class InterfaceTester { public static void main(String args[]){ Rectangle rect=new Rectangle(5,6); System.out.println("Area of rect = " + rect.area()); Circle cir=new Circle(2.0); System.out.println("Area of cir = " + cir.area()); } 运行结果 Area of rect = 30.0 Area of cir = 12.56

7.1.2 实现接口 ——例7_5 接口 声明接口类型的变量,并用它来访问对象 输出结果 7.1.2 实现接口 ——例7_5 接口 声明接口类型的变量,并用它来访问对象 public class VariableTester { public static void main(String []args) { Shape2D var1,var2; var1=new Rectangle(5,6); System.out.println("Area of var1 = " + var1.area()); var2=new Circle(2.0); System.out.println("Area of var2 = " + var2.area()); } 输出结果 Area of var1 = 30.0 Area of var2 = 12.56

7.1.2 实现接口 ——MovableObject接口 public interface  MovableObject { public boolean    start(); public void       stop(); public boolean    turn(int degrees); public double     fuelRemaining(); public void       changeSpeed(double kmPerHour); }

7.1.2 实现接口 ——MovableObject接口的实现 Plane、Car、 Train、 Boat 分别实现 MovableObject 接口 public class Plane implements  MovableObject { public int   seatCapacity; public Company  owner; public Date  lastRepairDate; //实现MovalbelObject接口的所有方法 public boolean start() { //启动飞机,成功则返回true } public void stop() { //停止 } public boolean turn(int degrees) { //转向,成功则返回true} public double fuelRemaining() { //返回燃料剩余量 } public void changeSpeed(double kmPerHour) { //改变速度 } //plane类自己的方法: public Date getLastRepairDate() { //... } public double calculateWindResistance() { //....} }

7.1.2 实现接口 ——RemoteControl类 为 MovableObjects安装遥控器(remote control) public class RemoteControl {   private MovableObject   machine;     RemoteControl(MovableObject m) {machine = m; }   //按下“启动”按钮: public void start() {     boolean okay = machine.start();     if (!okay) display("No Response on start");     //... } } remote control 构造方法的形参类型为 MovableObject,它可以是Plane, Car, Train, Boat, 等等

7.1.3 多重继承 多重继承 接口 Java的设计以简单实用为导向,不允许一个类有多个父类 但允许一个类可以实现多个接口,通过这种机制可实现多重继承 一个类实现多个接口的语法如下 [类修饰符] class 类名称 implements 接口1,接口2, … { … … }

7.1.3 多重继承 ——Car的例子 接口 Car类可以实现接口Insurable,Drivable,Sellable public class Car implements Insurable, Drivable, Sellable {    .... }

7.1.3 多重继承 ——例7_6 声明Circle类实现接口Shape2D和Color 接口 7.1.3 多重继承 ——例7_6 接口 声明Circle类实现接口Shape2D和Color Shape2D具有pi与area()方法,用来计算面积 Color则具有setColor方法,可用来赋值颜色 通过实现这两个接口,Circle类得以同时拥有这两个接口的成员,达到了多重继承的目的 interface Shape2D{ //声明Shape2D接口 final double pi=3.14; //数据成员一定要初始化 public abstract double area(); //抽象方法 } interface Color{ void setColor(String str); //抽象方法

7.1.3 多重继承 ——例7_6 接口 class Circle implements Shape2D,Color // 实现Circle类 { double radius; String color; public Circle(double r) //构造方法 radius=r; } public double area() //定义area()的处理方式 return (pi*radius*radius); public void setColor(String str) //定义setColor()的处理方式 color=str; System.out.println("color="+color);

7.1.3 多重继承 ——例7_6运行结果 测试类 接口 输出结果 public class MultiInterfaceTester{ 7.1.3 多重继承 ——例7_6运行结果 接口 测试类 public class MultiInterfaceTester{ public static void main(String args[]) { Circle cir; cir=new Circle(2.0); cir.setColor("blue"); System.out.println("Area = " + cir.area()); } 输出结果 color=blue Area = 12.56

7.1.4 接口的扩展 接口 接口的扩展 接口可通过扩展的技术派生出新的接口 原来的接口称为基本接口(base interface)或父接口(super interface) 派生出的接口称为派生接口(derived interface)或子接口(sub interface) 派生接口不仅可以保有父接口的成员,同时也可加入新成员以满足实际问题的需要 实现接口的类也必须实现此接口的父接口 接口扩展的语法 interface 子接口的名称 extends 父接口的名称1 { … … }

7.1.4 接口的扩展 ——例7_7 接口 Shape是父接口,Shape2D与Shape3D是其子接口。Circle类及Rectangle类实现接口Shape2D,而Box类及Sphere类实现接口Shape3D Shape接口 Shape2D接口 Shape3D接口 Sphere类 Box类 Rectangle类 Circle类

7.1.4 接口的扩展 ——例7_7 部分代码如下 接口 // 声明Shape接口 interface Shape{ 7.1.4 接口的扩展 ——例7_7 接口 部分代码如下 // 声明Shape接口 interface Shape{ double pi=3.14; void setColor(String str); } //声明Shape2D接口扩展了Shape接口 interface Shape2D extends Shape { double area();

7.1.4 接口的扩展 ——例7_7 接口 class Circle implements Shape2D { double radius; 7.1.4 接口的扩展 ——例7_7 接口 class Circle implements Shape2D { double radius; String color; public Circle(double r) { radius=r; } public double area() { return (pi*radius*radius); } public void setColor(String str){ color=str; System.out.println("color="+color); public class ExtendsInterfaceTester{ //测试类 public static void main(String []args) { Circle cir; cir=new Circle(2.0); cir.setColor("blue"); System.out.println("Area = " + cir.area());

7.1.4 接口的扩展 ——例7_7运行结果 运行结果 接口 说明 color=blue Area = 12.56 7.1.4 接口的扩展 ——例7_7运行结果 接口 运行结果 color=blue Area = 12.56 说明 首先声明了父接口Shape,然后声明其子接口Shape2D 之后声明类Circle实现Shape2D子接口,因而在此类内必须明确定义setColor()与area()方法的处理方式 最后在主类中我们声明了Circle类型的变量cir并创建新的对象,最后通过cir对象调用setColor()与area()方法

7.1.4 接口的扩展 ——Insurable接口的例子 FixedInsurable 和DepreciatingInsurable接口 都继承了Insurable接口 实现它们类也必须实现Insurable接口中的所有方法 public interface DepreciatingInsurable extends  Insurable {     public double computeFairMarketValue(); } public interface FixedInsurable extends  Insurable {     public int getEvaluationPeriod();

7.2 塑型 塑型(type-casting) 又称为类型转换 方式 隐式(自动)的类型转换 显式(强制)的类型转换

7.2.1 塑型的概念 塑型的对象 引用变量 塑型 将对象暂时当成更一般的对象来对待,并不改变其类型 只能被塑型为 任何一个父类类型 对象所属的类实现的一个接口 被塑型为父类或接口后,再被塑型回其本身所在的类

<<Interface>> 7.2.1 塑型的概念 ——一个例子 塑型 Manager对象 可以被塑型为Employee、Person、Object或Insurable, 不能被塑型为Customer、Company或Car Object Person Employee Customer Manager Company Car <<Interface>> Insurable

7.2.1 塑型的概念 ——隐式(自动)的类型转换 引用变量 被塑型成更一般的类 塑型 Employee emp; 7.2.1 塑型的概念 ——隐式(自动)的类型转换 塑型 引用变量 被塑型成更一般的类 Employee emp; emp = new Manager(); Car jetta = new Car(); Insurable item = jetta;

7.2.1 塑型的概念 ——显式(强制)的类型转换 引用变量:还原为本来的类型 Employee emp; 塑型 Manager man; 7.2.1 塑型的概念 ——显式(强制)的类型转换 塑型 引用变量:还原为本来的类型 Employee emp; Manager man; emp = new Manager(); man = (Manager)emp; //将emp强制塑型为本来的类型

7.2.2 塑型的应用 塑型 当一个类对象被塑型为其父类后,它提供的方法会减少 当Manager对象被塑型为Employee之后,它只能接收getName()及getEmployeeNumber()方法,不能接收getSalary()方法 将其塑型为本来的类型后,又能接收getSalary()方法了

7.2.3 方法的查找 如果在塑型前和塑型后的类中都提供了相同的方法,如果将此方法发送给塑型后的对象,那么系统将会调用哪一个类中的方法? 实例方法 类方法

7.2.3 方法的查找 ——实例方法 塑型 Manager man = new Manager(); 7.2.3 方法的查找 ——实例方法 塑型 Manager   man = new Manager(); Employee  emp1 = new Employee(); Employee  emp2 = (Employee)man; emp1.computePay(); // 调用Employee类中的computePay()方法 man.computePay();  // 调用Manager类中的computePay()方法 emp2.computePay(); // 调用Manager类中的computePay()方法

7.2.3 方法的查找 ——类方法 总是在变量声明时所属的类中进行查找 塑型 Manager man = new Manager(); 7.2.3 方法的查找 ——类方法 塑型 总是在变量声明时所属的类中进行查找 Manager man = new Manager(); Employee emp1 = new Employee(); Employee emp2 = (Employee)man; man.expenseAllowance(); //in Manager emp1.expenseAllowance(); //in Employee emp2.expenseAllowance(); //in Employee!!!

7.3 多态的概念 多态 是指不同类型的对象可以响应相同的消息 从相同的基类派生出来的多个类型可被当作同一种类型对待,可对这些不同的类型进行同样的处理,由于多态性,这些不同派生类对象响应同一方法时的行为是有所差别的 例如 所有的Object类的对象都响应toString()方法 所有的BankAccount类的对象都响应deposit()方法

7.3.1 多态的目的 多态的目的 多态的概念 所有的对象都可被塑型为相同的类型,响应相同的消息 使代码变得简单且容易理解 使程序具有很好的“扩展性”

7.3.1 多态的目的 ——一个例子 多态的概念 绘图 希望能够画出任意子类型对象的形状,可以在Shape 类中声明几个绘图方法,对不同的实际对象,采用不同的画法 if (aShape instanceof Circle) aShape.drawCircle(); if (aShape instanceof Triangle) aShape.drawTriangle(); if (aShape instanceof Rectangle)aShape.drawRectangle();

7.3.1 多态的目的 ——一个例子 更好的方式 多态的概念 在每个子类中都声明同名的draw()方法 以后绘图可如下进行 7.3.1 多态的目的 ——一个例子 多态的概念 更好的方式 在每个子类中都声明同名的draw()方法 以后绘图可如下进行 Shape s = new Circle(); s.draw(); Circle属于Shape的一种,系统会执行自动塑型 当调用方法draw时,实际调用的是Circle.draw() 在程序运行时才进行绑定,接下来介绍绑定的概念

7.3.2 绑定的概念 绑定 多态的概念 指将一个方法调用同一个方法主体连接到一起 根据绑定时期的不同,可分为 早期绑定(静态绑定)——方法的重载 程序运行之前执行绑定 晚期绑定(动态绑定)——方法的重写 也叫作“动态绑定”或“运行期绑定 基于对象的类别,在程序运行时执行绑定

7.3.2 绑定的概念 ——例7_8 仍以绘图为例,所有类都放在binding包中 多态的概念 基类Shape建立了一个通用接口 7.3.2 绑定的概念 ——例7_8 多态的概念 仍以绘图为例,所有类都放在binding包中 基类Shape建立了一个通用接口 class Shape { void draw() {} void erase() {} } 派生类覆盖了draw方法,为每种特殊类型的几何形状都提供独一无二的行为 class Circle extends Shape { void draw() { System.out.println("Circle.draw()"); } void erase() { System.out.println("Circle.erase()"); }

7.3.2 绑定的概念 ——例7_8 多态的概念 class Square extends Shape { void draw() 7.3.2 绑定的概念 ——例7_8 多态的概念 class Square extends Shape { void draw() { System.out.println("Square.draw()"); } void erase() { System.out.println("Square.erase()"); } } class Triangle extends Shape { { System.out.println("Triangle.draw()"); } { System.out.println("Triangle.erase()"); }

7.3.2 绑定的概念 ——例7_8 多态的概念 对动态绑定进行测试如下 public class BindingTester{ 7.3.2 绑定的概念 ——例7_8 多态的概念 对动态绑定进行测试如下 public class BindingTester{ public static void main(String[] args) { Shape[] s = new Shape[9]; int n; for(int i = 0; i < s.length; i++) { n = (int)(Math.random() * 3); switch(n) { case 0: s[i] = new Circle(); break; case 1: s[i] = new Square(); break; case 2: s[i] = new Triangle(); } for(int i = 0; i < s.length; i++) s[i].draw();

7.3.2 绑定的概念 ——例7_8运行结果 多态的概念 运行结果 说明 Square.draw() Triangle.draw() 7.3.2 绑定的概念 ——例7_8运行结果 多态的概念 运行结果 Square.draw() Triangle.draw() Circle.draw() 说明 编译的时候是无法知道s数组元素的具体类型到底是什么 运行的时候才能确定究竟是什么类型,所以是动态绑定 在主方法的循环体中,每次根据运行时产生的随机数生成指向一个Circle、Square或者Triangle的引用,所以每次运行都可能有不同的结果

7.4 多态的应用 多态的应用 多态的概念 技术基础 向上塑型技术:一个父类的引用变量可以指向不同的子类对象 动态绑定技术:运行时根据父类引用变量所指对象的实际类型执行相应的子类方法,从而实现多态性

7.4 多态的应用(续) ——例7_9 多态的概念 声明一个抽象类Driver及两个子类FemaleDriver及MaleDriver 7.4 多态的应用(续) ——例7_9 多态的概念 声明一个抽象类Driver及两个子类FemaleDriver及MaleDriver 在Diver类中声明了抽象方法drives,在两个子类中对这个方法进行了重写 public abstract class Driver { public Driver( ) { } public abstract void drives( ); }

7.4 多态的应用(续) ——例7_9 多态的概念 public class FemaleDriver extends Driver { 7.4 多态的应用(续) ——例7_9 多态的概念 public class FemaleDriver extends Driver { public FemaleDriver( ) { } public void drives( ) { System.out.println("A Female driver drives a vehicle."); } public class MaleDriver extends Driver { public MaleDriver( ) { } System.out.println("A male driver drives a vehicle.");

7.4 多态的应用(续) ——例7_9 多态的概念 运行结果 public class Test1 { 7.4 多态的应用(续) ——例7_9 多态的概念 public class Test1 { static public void main(String [ ] args) Driver a = new FemaleDriver( ); Driver b = new MaleDriver( ); a.drives( ); b.drives( ); } 运行结果 A Female driver drives a vehicle. A male driver drives a vehicle.

7.4 多态的应用(续) ——例7_9改进 多态的概念 所有类都放在drive包中 7.4 多态的应用(续) ——例7_9改进 多态的概念 所有类都放在drive包中 试想有不同种类的交通工具(vehicle),如公共汽车(bus)及小汽车(car),由此可以声明一个抽象类Vehicle及两个子类Bus及Car 对前面的drives方法进行改进,使其接收一个Vehicle类的参数,当不同类型的交通工具被传送到此方法时,可以输出具体的交通工具

7.4 多态的应用(续) ——例7_9改进 多态的概念 测试代码可改写如下: 并希望输出下面的结果 7.4 多态的应用(续) ——例7_9改进 多态的概念 测试代码可改写如下: public class DriverTest { static public void main(String [ ] args) { Driver a = new FemaleDriver( ); Driver b = new MaleDriver( ); Vehicle x = new Car( ); Vehicle y = new Bus( ); a.drives(x); b.drives(y); } 并希望输出下面的结果 A female driver drives a Car. A male driver drives a bus.

7.4 多态的应用(续) ——例7_9改进 Vehicle及其子类声明如下 多态的概念 7.4 多态的应用(续) ——例7_9改进 多态的概念 Vehicle及其子类声明如下 public abstract class Vehicle { private String type; public Vehicle( ) { } public Vehicle(String s) { type = s; } public abstract void drivedByFemaleDriver(); public abstract void drivedByMaleDriver(); }

7.4 多态的应用(续) ——例7_9改进 多态的概念 public class Bus extends Vehicle { 7.4 多态的应用(续) ——例7_9改进 多态的概念 public class Bus extends Vehicle { public Bus( ) { } public void drivedByFemaleDriver() { System.out.println("A female driver drives a bus."); } public void drivedByMaleDriver() { System.out.println("A male driver drives a bus."); } } public class Car extends Vehicle { public Car( ) { } { System.out.println("A Female driver drives a car."); } { System.out.println("A Male driver drives a car."); }

7.4 多态的应用(续) ——例7_9改进 多态的概念 对FemaleDriver及MaleDriver类中的drives方法进行改进,在drives方法的定义体中不直接输出结果,而是调用Bus及Car类中的相应方法 public abstract class Driver { public Driver() { } public abstract void drives(Vehicle v ); } public class FemaleDriver extends Driver{ public FemaleDriver( ) { } public void drives(Vehicle v){ v.drivedByFemaleDriver(); } public class MaleDriver extends Driver{ public MaleDriver( ) { } public void drives(Vehicle v){ v.drivedByMaleDriver(); }

7.4 多态的应用(续) ——例7_9改进运行结果 运行结果 多态的概念 说明 A Female driver drives a car. 7.4 多态的应用(续) ——例7_9改进运行结果 多态的概念 运行结果 A Female driver drives a car. A male driver drives a bus. 说明 这种技术称为二次分发(“double dispatching”),即对输出消息的请求被分发两次 首先根据驾驶员的类型被发送给一个类 之后根据交通工具的类型被发送给另一个类

7.6 内部类 内部类 在另一个类或方法的定义中定义的类 可访问其外部类中的所有数据成员和方法成员 可对逻辑上相互联系的类进行分组 对于同一个包中的其他类来说,能够隐藏 可非常方便地编写事件驱动程序 声明方式 命名的内部类:可在类的内部多次使用 匿名内部类:可在new关键字后声明内部类,并立即创建一个对象 假设外层类名为Myclass,则该类的内部类名为 Myclass$c1.class (c1为命名的内部类名) Myclass$1.class (表示类中声明的第一个匿名内部类)

7.6 内部类 ——Parcel1.java 内部类 public class Parcel1 { class Contents { //内部类 private int i = 11; public int value() { return i; } } class Destination { //内部类 private String label; Destination(String whereTo) { label = whereTo; } String readLabel() { return label; } public void ship(String dest) { Contents c = new Contents(); Destination d = new Destination(dest); System.out.println(d.readLabel());

7.6 内部类 ——Parcel1.java public static void main(String[] args) { 内部类 说明 Parcel1 p = new Parcel1(); p.ship("Tanzania"); } 说明 在Parcel1类中声明了两个内部类Contents、Destination 在ship方法中生成两个内部类对象,并调用了内部类中声明的一个方法

7.6 内部类 ——Parcel2.java 外部类的方法可以返回内部类的引用变量 内部类 public class Parcel2 { class Contents { private int i = 11; public int value() { return i; } } class Destination { private String label; Destination(String whereTo) { label = whereTo; } String readLabel() { return label; } public Destination to(String s){ return new Destination(s); } public Contents cont() { return new Contents(); }

7.6 内部类 ——Parcel2.java 内部类 说明 Contents c = cont(); public void ship(String dest) { Contents c = cont(); Destination d = to(dest); System.out.println(d.readLabel()); } public static void main(String[] args) { Parcel2 p = new Parcel2(); p.ship("Tanzania"); Parcel2 q = new Parcel2(); Parcel2.Contents c = q.cont(); Parcel2.Destination d =q.to("Borneo"); 说明 to()方法返回内部类Destination的引用 cont()方法返回内部类Contents的引用

7.6 内部类 ——内部类实现接口 内部类实现接口 内部类 例子 可以完全不被看到,而且不能被调用 7.6 内部类 ——内部类实现接口 内部类 内部类实现接口 可以完全不被看到,而且不能被调用 可以方便实现“隐藏实现细则”。你所能得到的仅仅是指向基类(base class)或者接口的一个引用 例子 abstract class Contents { abstract public int value(); } interface Destination { String readLabel();

7.6 内部类 ——Parcel3.java 内部类 public class Parcel3 { private class PContents extends Contents { private int i = 11; public int value() { return i; } } protected class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo;} public String readLabel() { return label; } public Destination dest(String s) { return new PDestination(s); } public Contents cont() { return new PContents(); }

7.6 内部类 ——Parcel3测试 内部类 说明 class Test { public static void main(String[] args) { Parcel3 p = new Parcel3(); Contents c = p.cont(); Destination d = p.dest("Tanzania"); // Illegal -- can't access private class: Parcel3.PContents c = p.new PContents(); } 说明 内部类PContents实现了抽象类Contents 内部类PDenstination实现了接口Destination 外部类Test中不能声明对private的内部类的引用

7.6 内部类 ——方法中的内部类 在方法内定义一个内部类 内部类 为实现某个接口,产生并返回一个引用 7.6 内部类 ——方法中的内部类 内部类 在方法内定义一个内部类 为实现某个接口,产生并返回一个引用 为解决一个复杂问题,需要建立一个类,而又不想它为外界所用

7.6 内部类 ——匿名的内部类 内部类 public class Parcel6 { public Contents cont() { 7.6 内部类 ——匿名的内部类 内部类 public class Parcel6 { public Contents cont() { return new Contents() { private int i = 11; public int value() { return i; } }; } public static void main(String[] args) { Parcel6 p = new Parcel6(); Contents c = p.cont();

7.6 内部类 ——匿名的内部类 基类需要一个含参数的构造方法 例子 内部类 public class Parcel7 { 7.6 内部类 ——匿名的内部类 内部类 基类需要一个含参数的构造方法 例子 public class Parcel7 { public Wrapping wrap(int x) { return new Wrapping(x) { public int value() { return super.value() * 47; } }; } public static void main(String[] args) { Parcel7 p = new Parcel7(); Wrapping w = p.wrap(10);

7.7 本章小结 本章内容 本章要求 接口作用及语法 塑型的概念及应用 多态的概念及引用 构造方法的调用顺序及其中的多态方法 内部内的有关知识 本章要求 理解接口、塑型、多态的概念并能熟练应用 熟练掌握构造方法的调用顺序,理解编写时需要注意的问题 掌握内部类的语法结构及其应用场合