SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground计算机科学学院夏羽Java程序设计基于Java语言的面向对象程序设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground第二部分Java面向对象编程Java程序设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground回顾•实现继承的关键字是什么?•使用继承有什么好处?•子类继承父类后,如何调用父类的属性和方法?•什么是抽象类?提问SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground第八章多态第一节没有多态会怎么样?Java程序设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground为什么使用多态1•实现一个主人类,当宠物饿了的时候需要给宠物喂食。•给主人类(Master)添加一个feed方法。–然而,不同宠物吃的东西不一样:–其次,不同宠物吃完食物恢复后体力值不一样:吃狗粮吃鱼狗狗企鹅问题健康值增加3狗狗健康值增加5企鹅分析SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground为什么使用多态2•狗狗类–增加狗狗吃食的方法•企鹅类–增加企鹅吃食的方法•创建主人类–编写给狗狗喂食的方法–编写给企鹅喂食的方法•编写测试方法–调用主人类给狗狗喂的方法–调用主人类给企鹅喂的方法分析演示:未使用多态实现给宠物喂食SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground为什么使用多态3publicclassMaster{publicvoidfeed(Dogdog){dog.eat();}publicvoidfeed(Penguinpgn){pgn.eat();}publicvoidfeed(XXXxxx){xxx.eat();}……}主人类……Mastermaster=newMaster();master.feed(dog);master.feed(penguin);master.feed(xxx);……测试方法频繁修改代码,代码可扩展性、可维护性差,如何优化?参数都是Pet类的子类可否使用一个feed(Petpet)实现对所有宠物的喂食?使用多态优化设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground为什么使用多态4•如果再领养XXX宠物,就需要给XXX喂食,怎么办?–添加XXX类,继承Pet类,实现吃食方法–修改Master类,添加给XXX喂食的方法问题SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground第八章多态第二节什么是多态?Java程序设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground什么是多态•生活中的多态–不同类型的打印机打印效果不同•程序中的多态多态:同一个引用类型,使用不同的实例而执行不同操作父类引用,子类对象使用同一类事物,由于事物的分类或者使用的条件不同,产生的结果也不同黑白打印机彩色打印机打印SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground多态的作用•如果主人不停的领养宠物,就要一直添加方法,有没有一劳永逸的方法?•既然狗、企鹅、兔子等都是宠物类,能不能只写一个函数,该函数接收一个Pet对象作为参数就可以了?•Pet类是抽象类,实现eat方法无意义,怎么办?•调用某个Pet类的引用到底调用了谁的方法?问题分析SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground使用父类作为方法形参实现多态•使用多态优化主人给宠物喂食……Dogdog=newDog();Mastermaster=newMaster();master.feed(dog);……publicclassMaster{publicvoidfeed(Petpet){}}主人类测试方法同一种操作方式,不同的操作对象使用父类作为方法形参注意使用父类作为形式参数,可以接受子类的对象作为实参。进入到方法之后,该对象仅能当做父类使用,无法访问子类的成员。SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground到底调用谁的方法•Pet类的eat()方法怎么写?•调用Pet类的eat()方法,之后究竟执行谁的方法?publicclassPet{publicabstractvoideat();}master.feed(dog);……publicvoidfeed(Petpet){pet.eat();}演示:使用多态实现给宠物喂食master.feed(pgn);……publicvoidfeed(Petpet){pet.eat();}父类对象引用实际指向的对象是谁,就执行谁的方法。注意在C++中,必须使用virtual关键字才能实现多态,Java中,所有方法都是virtual方法。SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground父类作为返回值•主人无聊的时候想随机地找一只宠物来玩。•使用随机数生成器java.util.Random类•随机数种子的使用•生成随机数的范围nextInt(intn)•如何返回宠物?问题分析SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground父类作为方法返回值•使用多态实现领养宠物–使用父类Pet作为方法返回值–实现思路•首先需要有一个宠物列表•在Master类添加领养方法chooseRandomPet(Pet[]pets)方法•调用随机数生成器,生成宠物的索引,然后返回选中的宠物publicclassMaster{publicPetchooseRandomPet(Pet[]pets){……}}使用父类作为返回值类型,可以返回任意子类的实例演示:使用多态随机的选择宠物SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground父类到子类的转换1•实现主人与宠物玩耍功能,不同的宠物玩法不一样–和狗狗玩接飞盘游戏,狗狗的健康值减少10,与主人亲密度增加5。–和企鹅玩游泳游戏,企鹅的健康值减少10,与主人亲密度增加5。•给Dog添加接飞盘方法catchFlyingDisc()•给Penguin添加游泳方法swim()•给主人添加playWith(Petpet)方法,然后playWith()方法中需要根据不同的宠物判断玩耍的内容,怎么办?问题分析SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground父类到子类的转换2•代码实现publicclassMaster{publicvoidplay(Petpet){pet.catchingFlyDisc();}}publicclassPenguinextendsPet{publicvoidswimming(){……}}publicclassDogextendsPet{publicvoidcatchingFlyDisc(){……}}狗狗类企鹅类主人类……Petpet=newDog();Mastermaster=newMaster();master.playWith(pet);……测试类报错,父类引用不能调用子类特有方法SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground父类到子类的转换3•父类到子类的转换–向下转型(强制类型转换)可以使用强制类型转换,将父类转换成子类类型publicclassMaster{publicvoidplay(Petpet){Dogdog=(Dog)pet;dog.catchingFlyDisc();}}演示:父类向子类的转换SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground判断父类实例的类别•instanceof运算符语法对象instanceof类或接口publicclassMaster{publicvoidplay(Petpet){if(petinstanceofDog){//如果传入的是狗狗Dogdog=(Dog)pet;dog.catchFlyingDisc();}elseif(petinstanceofPenguin){//如果传入的是企鹅Penguinpgn=(Penguin)pet;pgn.swim();}}}演示:使用多态实现主人与宠物玩耍SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground小结•实现多态有哪两个要素?•使用的多态有什么好处?提问SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforeground第八章多态第三节Object类Java程序设计SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforegroundObject类Java类库Object类是Java中所有类的父类SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforegroundObject类的方法获取当前对象所属的类信息返回当前对象本身的有关信息比较两个对象是否是相等生成当前对象的一个拷贝返回该对象的哈希代码值销毁对象时被调用的方法Object+finalgetClass():Class+toString():String+equals(Objectobj):boolean=clone():clone+hashCode():int=finalize():void和C++必须使用模板不同,Java中不知道类型的对象都可以用Object类来表示SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforegroundgetClass()方法System.out.println(obj.getClass());if(obj1.getClass()==obj2.getClass()){…}可以得到对象所属的类的信息,支持输出可以用于判断两个不知类型的对象是不是同一个类型注意1.getClass()方法是多态方法返回的是实际对象的类型2.getClass()方法的返回值是Class类型,Class类型也继承自Object3.getClass()方法是finial方法,不能在子类中重写SlidesbackgroundSlidestitlePagetitlebackgroundPagetitleforegroundtoString()方法•在System.out.println()中直接打印对象时,实际上是调用了对象的toString()方法•如果不在子类中重写toString()方法,