008.第八章.多态

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

为什么使用多态 1
问题
• 实现一个主人类,当宠物饿了的时候需要给宠物喂食。
分析
• 给主人类(Master)添加一个feed方法。
– 然而,不同宠物吃的东西不一样:
狗狗 吃狗粮 企鹅 吃鱼
– 其次,不同宠物吃完食物恢复后体力值不一样:
狗狗
健康值增加3 企鹅 健康值增加5
为什么使用多态 2
分析
• 狗狗类
return this == obj;
} }
经验
自定义类的时候,想想对象需不需要比较,如果是,则要重写equals()方法
clone()方法
• 可以创建本对象的复制品
– 复制出的对象是一个新对象 – 复制出的对象含有现有对象的值,而不是初始值
• clone法为protected,在非子类方法中不能直接调用 • 使用clone()方法比new一个对象,在复制要快
获取当前对象所属的类信息 返回当前对象本身的有关信息 比较两个对象是否是相等 生成当前对象的一个拷贝 返回该对象的哈希代码值 销毁对象时被调用的方法
和C++必须使用模板不同,Java中不知道类型的对象都可以用Object类来表示
getClass()方法
System.out.println(obj.getClass()); if(obj1.getClass() == obj2.getClass()) { … } 可以用于判断两个不知类型 的对象是不是同一个类型
hashCode()方法更多的是和HashSet或者HashTable一起使用,对 于hashCode()的详细讲解,我们将放到集合一章中进行。
finalize()方法
• 当一个对象在程序中不能再被使用,就成为一个无用对象
• 没有任何引用指向该对象
– Java虚拟机会周期性的释放无用对象,称为垃圾回收(Garbage Collection) – 在对象被垃圾回收的时候,垃圾回收器(Garbage Collector)会先 调用对象的finalize()方法,然后再销毁对象
父类作为方法返回值
• 使用多态实现领养宠物
– 使用父类Pet作为方法返回值 – 实现思路
• 首先需要有一个宠物列表 • 在Master类添加领养方法chooseRandomPet(Pet[] pets)方法 • 调用随机数生成器,生成宠物的索引,然后返回选中的宠物
public class Master {
clone()方法的使用还涉及到其他的知识,现在只要记住,该方法就是将一个对象 复制了一份,对复制后的对象进行修改,不会影响原对象。
hashCode()方法
• 它的实现是根据本地机器相关的 • equals()相等的两个对象,hashCode()一定相等 • equals()不相等的两个对象,却并不能证明他们的 hashCode()不相等 • Java中的很多类都重写了hashCode()方法,例如,String, Integer, Double等,他们都有自己内部实际存储的数据来 计算hashCode
使用父类作为 方法形参
同一种操作方式, 不同的操作对象
注意
使用父类作为形式参数,可以接受子类的对象作为实参。 进入到方法之后,该对象仅能当做父类使用,无法访问子类的成员。
到底调用谁的方法
• Pet类的eat()方法怎么写?
public class Pet { public abstract void eat();
• 如果主人不停的领养宠物,就要一直添加方法,有没有一 劳永逸的方法?
分析
• 既然狗、企鹅、兔子等都是宠物类,能不能只写一个函数, 该函数接收一个Pet对象作为参数就可以了? • Pet类是抽象类,实现eat方法无意义,怎么办? • 调用某个Pet类的引用到底调用了谁的方法?
使用父类作为方法形参实现多态
可否使用一个feed(Pet pet) 实现对所有宠物的喂食?
频繁修改代码,代码可扩展性、可维护性差, 如何优化? 使用多态优化设计
为什么使用多态 4
问题
• 如果再领养XXX宠物,就需要给XXX喂食,怎么办?
– 添加XXX类,继承Pet类,实现吃食方法 – 修改Master类,添加给XXX喂食的方法
public Pet chooseRandomPet(Pet[] pets){ …… }
使用父类作为 } 返回值类型,可以返回任意子类的实例
演示:使用多态随机的选择宠物
父类到子类的转换 1
问题
• 实现主人与宠物玩耍功能,不同的宠物玩法不一样
– 和狗狗玩接飞盘游戏,狗狗的健康值减少10,与主人亲密度增 加5。 – 和企鹅玩游泳游戏,企鹅的健康值减少10,与主人亲密度增加5。
}
报错,父类引用不能调用 子类特有方法
父类到子类的转换 3
• 父类到子类的转换
– 向下转型(强制类型转换)
public class Master { public void play(Pet pet){ Dog dog = (Dog)pet; dog.catchingFlyDisc();
可以使用强制类型转 换,将父类转换成子 类类型
参数都是Pet类的子类 public void feed( Penguin pgn ) { master.feed(dog); master.feed(penguin); pgn.eat();
} master.feed(xxx); ……
}
public void feed( XXX xxx ) {
xxx.eat(); } } ……
演示 :使用多态实现主人与宠物玩耍
小结
提问
• 实现多态有哪两个要素? • 使用的多态有什么好处?
Java 程序设计
第八章
多态
第三节 Object类
Object类
Java类库
Object类是Java中所 有类的父类
Object类的方法
Object
+final getClass():Class +toString(): String +equals(Object obj): boolean =clone(): clone +hashCode(): int =finalize(): void
Java 程序设计
第八章
多态
第二节 什么是多态?
什么是多态
• 生活中的多态
– 不同类型的打印机打印效果不同
黑白打印机
打印
彩色打印机
• 程序中的多态
使用同一类事物,由于事物的分类或者使用的条件不同,产生的结 果也不同
父类引用,子类对象
多态:同一个引用类型,使用不同的实例而执行不同操作
多态的作用
问题
可以得到对象所属的类 的信息,支持输出
注意
1. 2. 3.
getClass()方法是多态方法返回的是实际对象的类型 getClass()方法的返回值是Class类型,Class类型也继承自Object getClass()方法是finial方法,不能在子类中重写
toString()方法
• 在System.out.println()中直接打印对象时,实际上是调用 了对象的toString()方法 • 如果不在子类中重写toString()方法,则直接调用Object 对象的实现:
equals()方法
• 回忆String类:
– ==用于判断两个对象是不是同一个对象 – equals()方法用于判断两个对象是否具有相同的值
警告
如果在子类中不重写Object类的equals()方法,则equals()方法跟==完成的功能是一样 的!!!
public class Object { public boolean equals(Object obj) {
主人类
public class Master { public void play(Pet pet){ pet.catchingFlyDisc(); } …… Pet pet = new Dog();
测试类
Master master = new Master();
master.playWith(pet); ……
分析
• 给Dog添加接飞盘方法catchFlyingDisc( ) • 给Penguin添加游泳方法swim ( ) • 给主人添加playWith(Pet pet)方法,然后playWith()方法 中需要根据不同的宠物判断玩耍的内容,怎么办?
父类到子类的转换 2
• 代码实现
狗狗类 企鹅类
public class Penguin extends Pet { public void swimming () { …… } } public class Dog extends Pet { public void catchingFlyDisc() { …… } }
4. 无法主动销毁或调用finalize()方法,只能由虚拟机回收
Java程序设计
基于 Java 语言的面向对象程序设计
计算机科学学院 夏羽
Java 程序设计
第二部分
Java面向对象编程
回顾
提问
• • • •
实现继承的关键字是什么? 使用继承有什么好处? 子类继承父类后,如何调用父类的属性和方法? 什么是抽象类?
Java 程序设计
第八章
多态
第一节 没有多态会怎么样?
• 无法知道垃圾回收什么时候执行,可以使用System.gc()方 法来建议虚拟机进行垃圾回收
注意
1. finalize()方法不能等同于析构函数 2. 无法知道对象的finalize()方法什么时候会被调用 3. 即使是调用了System.gc(),垃圾回收也不是马上运行
3. 如果要进行资源回收,建议用显式方法进行,不能依赖finalize()方法
pet.eat(); } } 在C++中,必须使用virtual关键字才能实现多态,Java中,所有方法 都是virtual方法。 pet.eat();
注意
演示:使用多态实现给宠物喂食
父类作为返回值
问题
• 主人无聊的时候想随机地找一只宠物来玩。
分析
• • • •
使用随机数生成器java.util.Random类 随机数种子的使用 生成随机数的范围nextInt(int n) 如何返回宠物?
• 使用多态优化主人给宠物喂食
public class Master {
主人类
……
测试方法
public void feed( Pet pet ) { } }
Dog dog = new Dog(); Master master = new Master(); master.feed( dog ); ……
– 增加狗狗吃食的方法
• 企鹅类
– 增加企鹅吃食的方法
• 创建主人类
– 编写给狗狗喂食的方法 – 编写给企鹅喂食的方法
• 编写测试方法
– 调用主人类给狗狗喂的方法 – 调用主人类给企鹅喂的方法
演示 :未使用多态实现给宠物喂食
为什么使用多态 3
主人类
public class Master { public void feed( Dog dog ) { dog.eat(); 测试方法 …… Master master = new Master();
}
}
演示 :父类向子类的转换
判断父类实例的类别
• instanceoBiblioteka Baidu运算符
语法
对象 instanceof 类或接口
public class Master {
public void play(Pet pet){
if (pet instanceof Dog) { //如果传入的是狗狗 Dog dog = (Dog) pet; dog.catchFlyingDisc(); }else if (pet instanceof Penguin) { //如果传入的是企鹅 Penguin pgn = (Penguin) pet; pgn.swim(); } } }
public class Object {
public String toString() {
getClass().getname() + “@”+Integer.toHexString(hashCode()); } }
经验
为了调试方便,自定义类建议都重写toString()方法,并且当类更新之后,记得同步更新 toString()方法
}
• 调用Pet类的eat()方法,之后究竟执行谁的方法?
master.feed( dog ); master.feed( pgn );
……
…… 父类对象引用实际指向的对象是谁,就执行谁的方法。 public void feed( Pet pet ) { public void feed( Pet pet ) {
相关文档
最新文档