Java从零开始学十六(多态)
一、什么是多态
多态性是指允许不同类的对象对同一消息作出响应.多态性包括参数化多态性和包含多态性.多态性语言具有灵活、抽象、行为共享、代码共享的优势,很好的解决了应用程序函数同名问题.
多态有两种表现形式:重载和覆盖
首先说重载(overload),是发生在同一类中.与什么父类子类、继承毫无关系.
标识一个函数除了函数名外,还有函数的参数(个数和类型).也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同.
他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!
再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生.
我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍.
这样再调用这个方法的时候,就是执行子类中的过程了.父类中的函数就被覆盖了.(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)
多态有两种表现形式:重载和覆盖
首先说重载(overload),是发生在同一类中.与什么父类子类、继承毫无关系.
标识一个函数除了函数名外,还有函数的参数(个数和类型).也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同.
他们之间毫无关系,是不同的函数,只是可能他们的功能类似,所以才命名一样,增加可读性,仅此而已!
再说覆盖(override),是发生在子类中!也就是说必须有继承的情况下才有覆盖发生.
我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不爽,功能要变,那就把那个函数在子类中重新实现一遍.
这样再调用这个方法的时候,就是执行子类中的过程了.父类中的函数就被覆盖了.(当然,覆盖的时候函数名和参数要和父类中完全一样,不然你的方法对父类中的方法就不起任何作用,因为两者是两个函数,毫不关系)
二、简单实现
package com.pb.demo6; public abstract class Pet { private String name; //宠物名字 private String sex; //宠物性别 private int health; //宠物的健康值 //宠物看病的方法 abstract void toHospital(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getHealth() { return health; } public void setHealth(int health) { this.health = health; } }
package com.pb.demo6; /* * 小狗类 */ public class Dog extends Pet { @Override void toHospital() { //小狗看病的方法 System.out.println("小狗看病:打针、吃药!"); } } package com.pb.demo6; /* * 小猪类 */ public class Pig extends Pet { @Override void toHospital() { System.out.println("小猪看病:打针、睡觉!"); } } package com.pb.demo6; /* * 小鸟类 */ public class Bird extends Pet { @Override void toHospital() { //小鸟看病的方法 System.out.println("小鸟看病:吃药、休息!"); } }
package com.pb.demo6; /* * 宠物医生类 */ public class Doctor { //医生治疗方法 public void cure(Pet pet){ //将宠物传参 if(pet.getHealth()<50){ //判断健康值小于50 //调用看病的方法 pet.toHospital(); //将健康值设置为60,健康 pet.setHealth(60); } } }
测试类
package com.pb.demo6; /* * 测试类 */ public class Test { public static void main(String[] args) { //声明医生对象 Doctor dc=new Doctor(); //声明宠物对象为小鸟 Pet brid=new Bird(); //调用医生的治疗方法 dc.cure(brid); //声明宠物对象为小狗 Pet dog=new Dog(); //调用医生的治疗方法 dc.cure(dog); //声明宠物对象为小猪 Pet pig=new Pig(); //调用医生的治疗方法 dc.cure(pig); } }
结果:
小鸟看病:吃药、休息! 小狗看病:打针、吃药! 小猪看病:打针、睡觉!
三、对象的多态性
对象的多态性主要分为以下两种类型:
向上转型和向下转型
3.1 对象向上转型:
父类 父类对象 = 子类实例 ;
向上转型:子类对象 ->父类对象
对于向上转型,程序会自动完成,格式:
如上面的:
//声明宠物对象为小鸟 Pet brid=new Bird(); //声明宠物对象为小狗 Pet dog=new Dog(); //声明宠物对象为小猪 Pet pig=new Pig();
编译时类型为:Pet,而运行时类型为具体的类型
也就是说编译时类型由声明该变量时使用类型决定,而运行时类型由实际赋给该变量的对象决定
3.2 对象向下转型:
向下转型:父类对象 ->子类对象
对于向下转型时,必须明确的指明要转型的子类类型,格式:
子类 子类对象 = (子类)父类实例 ;强制类型转换
上面的例中,子类没有自己的方法,如果子类有自己的方法,医生类中还能调用吗?显然不能,因为是向上转为父类后,只能调用父类的方法,如果要调用子类的方法就需要用到向下转型要用到instannceof
四、instanceof 关键字
在java中可以使用instanceof关键字判断一个对象到底是那个类的实例
对象 instanceof 类 ->返回boolean类型
package com.pb.demo6; public abstract class Pet { private String name; //宠物名字 private String sex; //宠物性别 private int health; //宠物的健康值 //宠物看病的方法 abstract void toHospital(); public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getHealth() { return health; } public void setHealth(int health) { this.health = health; } }
package com.pb.demo6; /* * 小鸟类 */ public class Bird extends Pet { @Override void toHospital() { //小鸟看病的方法 System.out.println("小鸟看病:吃药、休息!"); } public void fly(){ System.out.println("小鸟会飞!"); } }
package com.pb.demo6; /* * 小狗类 */ public class Dog extends Pet { @Override void toHospital() { //小狗看病的方法 System.out.println("小狗看病:打针、吃药!"); } public void run(){ System.out.println("小狗在地上跑!"); } }
package com.pb.demo6; /* * 小猪类 */ public class Pig extends Pet { @Override void toHospital() { System.out.println("小猪看病:打针、睡觉!"); } public void sleep(){ System.out.println("小猪要睡觉!"); } }
package com.pb.demo6; /* * 宠物医生类 */ public class Doctor { //医生治疗方法 public void cure(Pet pet){ //将宠物传参 if(pet.getHealth()<50){ //判断健康值小于50 //调用看病的方法 pet.toHospital(); //将健康值设置为60,健康 pet.setHealth(60); //判断是宠物类型 if(pet instanceof Dog){ //向下转型,强制类型转制 Dog dog=(Dog)pet; //调用小狗自己的方法 dog.run(); }else if(pet instanceof Bird){ //向下转型,强制类型转制 Bird bird=(Bird)pet; //调用小鸟自己的方法 bird.fly(); }else if(pet instanceof Pig){ //向下转型,强制类型转制 Pig pig=(Pig)pet; //调用小猪自己的方法 pig.sleep(); } } } }
package com.pb.demo6; /* * 测试类 */ public class Test { public static void main(String[] args) { //声明医生对象 Doctor dc=new Doctor(); //声明宠物对象为小鸟 Pet brid=new Bird(); //调用医生的治疗方法 dc.cure(brid); //声明宠物对象为小狗 Pet dog=new Dog(); //调用医生的治疗方法 dc.cure(dog); //声明宠物对象为小猪 Pet pig=new Pig(); //调用医生的治疗方法 dc.cure(pig); } }
结果:
小鸟看病:吃药、休息! 小鸟会飞! 小狗看病:打针、吃药! 小狗在地上跑! 小猪看病:打针、睡觉! 小猪要睡觉!
五、父类做为形参
package com.pb.demo2; /* * 商品类 */ public class Goods { //打印商品价格方法 public void printPrice(){ System.out.println("打印商品价格"); } } package com.pb.demo2; /* * 食品类 */ public class Foods extends Goods { @Override public void printPrice() { System.out.println("打印食品类的商品价格!"); } } package com.pb.demo2; /* * 电视类 */ public class TVs extends Goods { @Override public void printPrice() { System.out.println("打印电视类商品价格!"); } }
测试类:
package com.pb.demo2; public class Test { public static void main(String[] args) { //声明3 个商品价格 Goods good=new Goods(); Foods food=new Foods(); TVs tvs=new TVs(); //调用方法 showPrice(good); showPrice(food); showPrice(tvs); } //显示商品价格方法 static void showPrice(Goods good){ good.printPrice(); } }
结果:
打印商品价格
打印食品类的商品价格!
打印电视类商品价格!