继承与多态北京理工大学计算机系第六讲
2009-7-29 北京理工大学计算机系 2
本讲内容
继承
多态继承( Inheritance)
第一部分
2009-7-29 北京理工大学计算机系 4
引例
一个最简单的窗口,SimplestWindow.java
问题:
现在要生成一个红色的窗体有几种方法?
2009-7-29 北京理工大学计算机系 5
最直观的方法
( 1)在 main()函数中增加一句,SetBackground(… );
这是过程式的思维方法,受 C的毒害太深!
(2)复制所有 Window.java源文件到新文件中,然后修改。
(3)增加一个构造函数,传递一个参数表明要生成红色的窗体居然有这么蠢的程序员用这种作法,我无言了。
题外话:出了名了中印程序员,数组 vs 链表,
可行的方法,基本合格
2009-7-29 北京理工大学计算机系 6
一个职业程序员的作法
使用组合
使用继承
2009-7-29 北京理工大学计算机系 7
使用组合
首先需要改造 SimplestWindow以便于重用代码。
新建一个类,以 SimplestWindow的一个对象作为类成员
实例,UseCompositionExample.java
2009-7-29 北京理工大学计算机系 8
使用继承
新建一个 RedWindow类,从
SimplestWindows中派生出来
实例,UseInheritsExample.java
2009-7-29 北京理工大学计算机系 9
组合 vs 继承
对比两个示例:
( 1)使用组合的可以使用 SimplestWindow
的所有 Public方法,因而灵活度高
( 2)使用继承的代码特别少,使用者不需要了解 SimplestWindow的任何细节。
面向对象设计通用原则:
组合优先于继承
2009-7-29 北京理工大学计算机系 10
继承的语法
Class 子类名 extends 父类名
{
……
}
父类( parent class) =基类( base class) =
超类( super class)
2009-7-29 北京理工大学计算机系 11
继承之后父类与子类的关系
IS-A关系:子类就是父类的一种特例
扩充关系:子类拥有父类所没有的功能你有的我也有,
我有的你没有!?
2009-7-29 北京理工大学计算机系 12
类访问权限
Public:所有外界类均可访问
Private:所有外界类均不可访问
Protected:所有外界类都不可以访问,但子类可以访问
Friendly:包中的类可以访问注意:区分 Java与 C++中的不同。
2009-7-29 北京理工大学计算机系 13
类访问存限实例
现场编程展示
2009-7-29 北京理工大学计算机系 14
设计类访问权限的基本原则
所有不必让外人知道的东西都是私有的。
所有需要向外提供的服务都是公有的。
所有的祖传绝招,传子不传女的都是保护的。
2009-7-29 北京理工大学计算机系 15
继承条件下的构造函数调用:
Child.java(Inherit文件夹内 )
注意:父类与子类之间构造函数的调用关系
修改代码,显式调用父类的另一个构造函数
移动调用构造函数的语句到第二行,发生什么结果?
2009-7-29 北京理工大学计算机系 16
思索:
为什么子类的构造函数在运行之前,必须调用父类的构造函数?
提示:
构造函数的主要作用是什么?
从这个方面去想!
2009-7-29 北京理工大学计算机系 17
不允许继承的类
final class 类名
{
}
多态( polymorphism)
第二部分
2009-7-29 北京理工大学计算机系 19
多态
多态的最本质特征就是父类引用可以指向子类引用。
张三(子类的实例)是一个人(父类)的实例,
则人的对象类型变量可以指向张三。
Instanceof运算符用于判断某一对象是哪一个类的对象
2009-7-29 北京理工大学计算机系 20
子类对象与基类对象
子类对象可以被当成基类对象使用 !
SimplestWindow sw=new RedWindow();
Window w=sw;
小结,
总是可以让更一般的对象容纳更具体化的对象,
2009-7-29 北京理工大学计算机系 21
子类对象与基类对象 (二 )
基类对象要赋给子类对象变量,必须执行类型转换,语法,
子类对象变量 =(子类名 )基类对象名 ;
也不能乱转换 !转换失败 Java会抛出异常,
ClassCastException
2009-7-29 北京理工大学计算机系 22
子类对象与基类对象 (三 )
每个对象都可以赋值给 Object变量。
这个基本原则构建了多态的根基。
2009-7-29 北京理工大学计算机系 23
子类与父类的方法
子类函数,父类没有 ----扩充( Extends)
子类函数父类也有 ---覆盖( Overrides)
注意,两者完全一样
子类有父类的同名函数,但参数类型或数目不一样 ---重载( Overloads)
如果创建子类对象,可使用的方法( method)是不同的。举例说明
2009-7-29 北京理工大学计算机系 24
方法覆盖( 1)
子类可以覆盖基类的方法示例,ww2.java,覆盖 Windows类的 setSize()
注意,静态方法不能覆盖 !
编译器实现覆盖的方法是,滞后绑定,(late bind),因为它编译时无法知道到底调用哪个方法
2009-7-29 北京理工大学计算机系 25
方法覆盖( 2)
方法覆盖要求子类与父类的方法一模一样,
否则就是 方法重载 !
举例说明在子类中,若要使用父类中被隐藏的方法,可以使用 super关键字
虚方法调用只用同样的一个语句,在运行时可以根据对象类型来执行不同的操作
2009-7-29 北京理工大学计算机系 26
方法覆盖( 3)
应用覆盖的原则:
( 1)覆盖方法的允许访问范围不能小于原方法:
( 2)覆盖方法所抛出的异常不能比原方法更多;
2009-7-29 北京理工大学计算机系 27
名字冲突
如果父类与子类有一个变量名相同,怎么办?
如果子类与父类有相同的数据成员,则子类中的数据成员会代替或隐藏父类的成员,这时,可以用 super关键字来访问父类中的成员 ;
如果子类被当作父类使用,则通过子类访问的此数据成员是 父类 的 !
课堂练习,
阅读 Citrus.java,写出运行结果,
2009-7-29 北京理工大学计算机系 28
示例运行结果
2009-7-29 北京理工大学计算机系 29
final
以 final声明的类不允许继承,如
Java.lang.Math类
以 final声明的方法不允许覆盖,
以 final声明的变量不允许更改。
2009-7-29 北京理工大学计算机系 30
抽象类
abstract:抽象类,只定义什么方法应该存在,
不能生成对象,必须派生出一个子类,并在子类中实现其未实现的方法
在方法前加上 abstract就形成抽象方法,只有外壳,没有实现代码
2009-7-29 北京理工大学计算机系 31
抽象类、抽象方法实例
abstract class Person
{
public abstract String getDescription();
}
2009-7-29 北京理工大学计算机系 32
注意
一个抽象类中可以包含非抽象方法和成员变量。
包含抽象方法的类一定是抽象类,但抽象类中的方法不一定是抽象方法
2009-7-29 北京理工大学计算机系 33
从抽象类继承
从抽象类继承的子类必须实现父类的所有抽象方法,否则,
它仍然是抽象类
class Employee extends Person
{
public String getDescription()
{
//Do Something...
return "";
}
}
2009-7-29 北京理工大学计算机系 34
使用抽象类
抽象类不能创建对象,一般用它来保存子类对象。
实例:
Person p;
p=new Employee();
以下语句总是成立的:
抽象类 抽象类型变量 =new具体子类()
2009-7-29 北京理工大学计算机系 35
学会画类的 UML图例区分抽象基类与具体子类
2009-7-29 北京理工大学计算机系 36
抽象类的实例
PersonTest.java
2009-7-29 北京理工大学计算机系 37
习题
三个类,
class Mammal{}
class Dog extends Mammal {}
class Cat Extends Mammal{}
每个类有以下变量,
Mammal m;
Dog d=new Dog();
Cat c=new Cat();
2009-7-29 北京理工大学计算机系 38
习题 (续 )
下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?
m=d;
d=m;
d=(Dog)m;
d=c;
c=(Cat)m; 代码实例:TestCast.java
2009-7-29 北京理工大学计算机系 39
Object类
Object类是所有 Java类的始祖,
用 JCreator查看 Object类的接口,并作简要解释
2009-7-29 北京理工大学计算机系 40
Object的 ToString方法
示例,Fruit.java
在,+”运算中,当任何一个对象与一个 String对象连接时,会隐式地调用其 toString()方法,
2009-7-29 北京理工大学计算机系 41
我糊涂了!
为什么要用多态?这么复杂!它有什么好处?
最大的好处是:
当你要修改程序并扩充系统时,你需要修改的地方最少,对其它部分代码的影响 最小 !
千万不要小看这两个,最,字!
2009-7-29 北京理工大学计算机系 42
多态在面向对象设计中的巧妙应用
,设计模式,一书中的图文混排编辑器的设计方案展示一个比较完整的面向对象设计实例
2009-7-29 北京理工大学计算机系 43
一个复杂的示例
示例,
MyDrawExample
( 1)通过 UML描述整个软件系统
( 2)多态的方法使程序易于扩充
2009-7-29 北京理工大学计算机系 2
本讲内容
继承
多态继承( Inheritance)
第一部分
2009-7-29 北京理工大学计算机系 4
引例
一个最简单的窗口,SimplestWindow.java
问题:
现在要生成一个红色的窗体有几种方法?
2009-7-29 北京理工大学计算机系 5
最直观的方法
( 1)在 main()函数中增加一句,SetBackground(… );
这是过程式的思维方法,受 C的毒害太深!
(2)复制所有 Window.java源文件到新文件中,然后修改。
(3)增加一个构造函数,传递一个参数表明要生成红色的窗体居然有这么蠢的程序员用这种作法,我无言了。
题外话:出了名了中印程序员,数组 vs 链表,
可行的方法,基本合格
2009-7-29 北京理工大学计算机系 6
一个职业程序员的作法
使用组合
使用继承
2009-7-29 北京理工大学计算机系 7
使用组合
首先需要改造 SimplestWindow以便于重用代码。
新建一个类,以 SimplestWindow的一个对象作为类成员
实例,UseCompositionExample.java
2009-7-29 北京理工大学计算机系 8
使用继承
新建一个 RedWindow类,从
SimplestWindows中派生出来
实例,UseInheritsExample.java
2009-7-29 北京理工大学计算机系 9
组合 vs 继承
对比两个示例:
( 1)使用组合的可以使用 SimplestWindow
的所有 Public方法,因而灵活度高
( 2)使用继承的代码特别少,使用者不需要了解 SimplestWindow的任何细节。
面向对象设计通用原则:
组合优先于继承
2009-7-29 北京理工大学计算机系 10
继承的语法
Class 子类名 extends 父类名
{
……
}
父类( parent class) =基类( base class) =
超类( super class)
2009-7-29 北京理工大学计算机系 11
继承之后父类与子类的关系
IS-A关系:子类就是父类的一种特例
扩充关系:子类拥有父类所没有的功能你有的我也有,
我有的你没有!?
2009-7-29 北京理工大学计算机系 12
类访问权限
Public:所有外界类均可访问
Private:所有外界类均不可访问
Protected:所有外界类都不可以访问,但子类可以访问
Friendly:包中的类可以访问注意:区分 Java与 C++中的不同。
2009-7-29 北京理工大学计算机系 13
类访问存限实例
现场编程展示
2009-7-29 北京理工大学计算机系 14
设计类访问权限的基本原则
所有不必让外人知道的东西都是私有的。
所有需要向外提供的服务都是公有的。
所有的祖传绝招,传子不传女的都是保护的。
2009-7-29 北京理工大学计算机系 15
继承条件下的构造函数调用:
Child.java(Inherit文件夹内 )
注意:父类与子类之间构造函数的调用关系
修改代码,显式调用父类的另一个构造函数
移动调用构造函数的语句到第二行,发生什么结果?
2009-7-29 北京理工大学计算机系 16
思索:
为什么子类的构造函数在运行之前,必须调用父类的构造函数?
提示:
构造函数的主要作用是什么?
从这个方面去想!
2009-7-29 北京理工大学计算机系 17
不允许继承的类
final class 类名
{
}
多态( polymorphism)
第二部分
2009-7-29 北京理工大学计算机系 19
多态
多态的最本质特征就是父类引用可以指向子类引用。
张三(子类的实例)是一个人(父类)的实例,
则人的对象类型变量可以指向张三。
Instanceof运算符用于判断某一对象是哪一个类的对象
2009-7-29 北京理工大学计算机系 20
子类对象与基类对象
子类对象可以被当成基类对象使用 !
SimplestWindow sw=new RedWindow();
Window w=sw;
小结,
总是可以让更一般的对象容纳更具体化的对象,
2009-7-29 北京理工大学计算机系 21
子类对象与基类对象 (二 )
基类对象要赋给子类对象变量,必须执行类型转换,语法,
子类对象变量 =(子类名 )基类对象名 ;
也不能乱转换 !转换失败 Java会抛出异常,
ClassCastException
2009-7-29 北京理工大学计算机系 22
子类对象与基类对象 (三 )
每个对象都可以赋值给 Object变量。
这个基本原则构建了多态的根基。
2009-7-29 北京理工大学计算机系 23
子类与父类的方法
子类函数,父类没有 ----扩充( Extends)
子类函数父类也有 ---覆盖( Overrides)
注意,两者完全一样
子类有父类的同名函数,但参数类型或数目不一样 ---重载( Overloads)
如果创建子类对象,可使用的方法( method)是不同的。举例说明
2009-7-29 北京理工大学计算机系 24
方法覆盖( 1)
子类可以覆盖基类的方法示例,ww2.java,覆盖 Windows类的 setSize()
注意,静态方法不能覆盖 !
编译器实现覆盖的方法是,滞后绑定,(late bind),因为它编译时无法知道到底调用哪个方法
2009-7-29 北京理工大学计算机系 25
方法覆盖( 2)
方法覆盖要求子类与父类的方法一模一样,
否则就是 方法重载 !
举例说明在子类中,若要使用父类中被隐藏的方法,可以使用 super关键字
虚方法调用只用同样的一个语句,在运行时可以根据对象类型来执行不同的操作
2009-7-29 北京理工大学计算机系 26
方法覆盖( 3)
应用覆盖的原则:
( 1)覆盖方法的允许访问范围不能小于原方法:
( 2)覆盖方法所抛出的异常不能比原方法更多;
2009-7-29 北京理工大学计算机系 27
名字冲突
如果父类与子类有一个变量名相同,怎么办?
如果子类与父类有相同的数据成员,则子类中的数据成员会代替或隐藏父类的成员,这时,可以用 super关键字来访问父类中的成员 ;
如果子类被当作父类使用,则通过子类访问的此数据成员是 父类 的 !
课堂练习,
阅读 Citrus.java,写出运行结果,
2009-7-29 北京理工大学计算机系 28
示例运行结果
2009-7-29 北京理工大学计算机系 29
final
以 final声明的类不允许继承,如
Java.lang.Math类
以 final声明的方法不允许覆盖,
以 final声明的变量不允许更改。
2009-7-29 北京理工大学计算机系 30
抽象类
abstract:抽象类,只定义什么方法应该存在,
不能生成对象,必须派生出一个子类,并在子类中实现其未实现的方法
在方法前加上 abstract就形成抽象方法,只有外壳,没有实现代码
2009-7-29 北京理工大学计算机系 31
抽象类、抽象方法实例
abstract class Person
{
public abstract String getDescription();
}
2009-7-29 北京理工大学计算机系 32
注意
一个抽象类中可以包含非抽象方法和成员变量。
包含抽象方法的类一定是抽象类,但抽象类中的方法不一定是抽象方法
2009-7-29 北京理工大学计算机系 33
从抽象类继承
从抽象类继承的子类必须实现父类的所有抽象方法,否则,
它仍然是抽象类
class Employee extends Person
{
public String getDescription()
{
//Do Something...
return "";
}
}
2009-7-29 北京理工大学计算机系 34
使用抽象类
抽象类不能创建对象,一般用它来保存子类对象。
实例:
Person p;
p=new Employee();
以下语句总是成立的:
抽象类 抽象类型变量 =new具体子类()
2009-7-29 北京理工大学计算机系 35
学会画类的 UML图例区分抽象基类与具体子类
2009-7-29 北京理工大学计算机系 36
抽象类的实例
PersonTest.java
2009-7-29 北京理工大学计算机系 37
习题
三个类,
class Mammal{}
class Dog extends Mammal {}
class Cat Extends Mammal{}
每个类有以下变量,
Mammal m;
Dog d=new Dog();
Cat c=new Cat();
2009-7-29 北京理工大学计算机系 38
习题 (续 )
下列语句哪一个将引起编译错误?为什么?哪一个会引起运行时错误?为什么?
m=d;
d=m;
d=(Dog)m;
d=c;
c=(Cat)m; 代码实例:TestCast.java
2009-7-29 北京理工大学计算机系 39
Object类
Object类是所有 Java类的始祖,
用 JCreator查看 Object类的接口,并作简要解释
2009-7-29 北京理工大学计算机系 40
Object的 ToString方法
示例,Fruit.java
在,+”运算中,当任何一个对象与一个 String对象连接时,会隐式地调用其 toString()方法,
2009-7-29 北京理工大学计算机系 41
我糊涂了!
为什么要用多态?这么复杂!它有什么好处?
最大的好处是:
当你要修改程序并扩充系统时,你需要修改的地方最少,对其它部分代码的影响 最小 !
千万不要小看这两个,最,字!
2009-7-29 北京理工大学计算机系 42
多态在面向对象设计中的巧妙应用
,设计模式,一书中的图文混排编辑器的设计方案展示一个比较完整的面向对象设计实例
2009-7-29 北京理工大学计算机系 43
一个复杂的示例
示例,
MyDrawExample
( 1)通过 UML描述整个软件系统
( 2)多态的方法使程序易于扩充