一、多态的概念
在面向对象语言中,多态是指在一棵继承树中的类中可以有多个同名但不同方法体及不同形参的方法。通常有两种途径实现多态:方法的重载和覆盖。
多态性允许以统一的风格处理已存在的变量及相关的类。多态性使得向系统里增加新功能变得容易。继承性和多态性是降低软件复杂性有有效技术。
二、实现多态
多态(polymoph)指的是“执行期间(而非编译期间)”判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。多态也叫动态绑定,也叫迟绑定。
多态的存在有三个必要条件:
- 要有继承
- 要有方法重写
- 父类引用指向子类对象
package com.duotai; /** * 狗狗类,宠物的子类 */ public class Dog extends Pet { private String strain="哈士奇";// 品种 //无参构造方法 public Dog(String name,int health,int love,String strain) { super(name,health,love); this.strain = strain; System.out.println("dog类构造方法"); } public String getStrain() { return strain; } public void setStrain(String strain) { this.strain = strain; } //重写父类方法 public void print() { System.out.println("宠物的自白: 我的名字叫" + this.getName() + ",我的品种是" + this.getStrain()+",我的健康值是" + this.getHealth() + ",我和主人的亲密程度是" + this.getLove() + "。"); } public void toHospital(){ if(this.getHealth()<60){ System.out.println("给狗狗打针、吃药"); this.setHealth(60); } } }
package com.duotai; /** * 企鹅类 */ public class Penguin extends Pet { private String sex="Q仔";// 企鹅性别 //构造方法 public Penguin(String name,int health,int love,String sex) { super(name,health,love); this.sex = sex; System.out.println("penguin类构造方法"); } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } //重写父类方法 public void print() { System.out.println("宠物的自白: 我的名字叫" + this.getName() + ",我的性别是" + this.getSex()+",我的健康值是" + this.getHealth() + ",我和主人的亲密程度是" + this.getLove() + "。"); } public void toHospital(){ if(this.getHealth()<50){ System.out.println("给企鹅吃药、疗养"); this.setHealth(70); } } }
package com.duotai; /** * 宠物类,狗狗和企鹅的父类 */ public class Pet { private String name = "无名氏";// 昵称 private int health = 100;// 健康值 private int love = 20;// 亲密度 /** * 无参构造方法 */ public Pet() { System.out.println("父类无参构造方法"); } /** * 有参构造方法 * @param name 昵称 */ public Pet(String name,int health,int love) { this.name = name; this.health = health; this.love = love; System.out.println("父类有参构造方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHealth() { return health; } public void setHealth(int health) { if(health<0||health>100){ System.out.println("健康值应该在0至100之间,默认值为60"); this.health=60; return; } this.health = health; } public int getLove() { return love; } public void setLove(int love) { if(love<0||love>100){ System.out.println("亲密度应该在0至100之间,默认值为15"); this.love=15; return; } this.love = love; } /** * 输出宠物信息 */ public void print() { System.out.println("宠物的自白: 我的名字叫" + this.name + ",我的健康值是" + this.health + ",我和主人的亲密程度是" + this.love + "。"); } public void toHospital(){ } }
package com.duotai; /* * 主人类 */ public class Master { // //给狗狗看病方法 // public void cure(Dog dog){ // if(dog.getHealth()<60){ // System.out.println("给宠物打针、吃药"); // dog.setHealth(60); // } // } // //给企鹅看病方法 // public void cure(Penguin pgn){ // if(pgn.getHealth()<60){ // System.out.println("给宠物吃药、疗养"); // pgn.setHealth(70); // } // } //给宠物看病 public void cure(Pet pe){ pe.toHospital(); } }
package com.duotai; //测试类 public class Test { public static void main(String[] args) { // 1、创建宠物对象pet并输出信息 // Pet pet = new Pet("苏苏",99,60); // pet.print(); Master master = new Master(); //实例化主人对象 // 2、创建狗狗对象dog并输出信息 //Dog dog = new Dog("丫丫",45,40,"牧羊犬"); Pet pdog = new Dog("丫丫",45,40,"牧羊犬"); //向上转型 master.cure(pdog); pdog.print(); // 3、创建企鹅对象pgn并输出信息 // Penguin pgn = new Penguin("果果",85,20,"Q妹"); // pgn.print(); //同一引用类型 不同的实例 Pet ppegn = new Penguin("果果",10,20,"Q妹"); //多态:1、方法重写是实现多态的基础 2、同一引用类型,使用不同的实例而执行不同操作 master.cure(ppegn); //执行不同操作 ppegn.print(); } }
三、向上转型和向下转型
1.向上转型:<父类型> <引用变量名> = new <子类型>();
例如:int i = 3;
double a = i; //自动进行类型转换
double b = 3.14;
int c = (int)b; //强制进行类型转换
- 将一个父类的引用指向一个子类对象成为向上转型
- 此时通过父类引用调用的方法是子类覆盖或继承了父类的方法,而不是父类的方法
- 此时通过父类引用变量无法直接调用子类特有的方法
2.向下转型:<子类型> <引用变量名> = (<子类型>)<父类型引用变量>;
将一个指向子类对象的父类引用赋给一个子类的引用,即将父类类型转换为子类类型
例如:Dog dog = (Dog)pet; //将父类引用pet转换为Dog类型
四、instance运算符
在向下转型的过程中,如果不是转换为真实子类类型,会出现转换异常,java中提供了instance运算符进行类型的判断
public void cure(Pet pe){ if(pe instanceof Dog){ //... }else if(pe instanceof Penguin){ //..... } }
注意:使用instance时,对象的类型必须和instance后面的参数所指定的类有继承关系,否则会出现编译错误
五、多态的应用
- 可替换性:多态已存在的代码具有可替换性
- 可扩充性:对代码具有可扩充性,增加新的子类不影响已存在类的多态性、继承性
- 接口性:多态时父类想子类提供了一个共同接口,有子类来具体实现
- 灵活性:多态在应用中体现了灵活多样的操作,提高了使用效率
- 简化性:简化了引用软件的代码编写和修改过程,尤其是在处理大量对象的晕眩和操作时
- 2中应用形式:
- 使用父类作为方法的形参
- 使用父类作为方法的返回值
package com.abstractInterface; /* * 动物类 * @author yutianbao * @param * @date 2019/3/20 13:32 * @return * @Motto: good good study,day day up */ public abstract class Animals { //抽象类 //叫 public abstract void cry(); } /* * 狗狗类 * @author yutianbao * @param * @date 2019/3/20 13:34 * @return * @Motto: good good study,day day up */ class Dog extends Animals{ public void cry(){ System.out.println("狗狗叫:汪汪汪"); } } /* * 猫类 * @author yutianbao * @param * @date 2019/3/20 13:37 * @return * @Motto: good good study,day day up */ class Cat extends Animals{ public void cry(){ System.out.println("猫叫:喵喵喵"); } } /* * 鸭子类 * @author yutianbao * @param * @date 2019/3/20 13:37 * @return * @Motto: good good study,day day up */ class Duck extends Animals{ public void cry(){ System.out.println("鸭子叫:嘎嘎嘎"); } }
package com.abstractInterface; /* * 主人类 * @author yutianbao * @param * @date 2019/3/20 13:40 * @return * @Motto: good good study,day day up */ public class MasterPerson { //捐赠给别人动物 public Animals domateAnimals(String type){ Animals animals = null; if(type.equals("dog")){ animals = new Dog(); }else if(type.equals("cat")){ animals = new Cat(); }else if(type.equals("duck")){ animals = new Duck(); } return animals; } }
package com.abstractInterface; /* * 测试类 * @author yutianbao * @param * @date 2019/3/20 13:51 * @return * @Motto: good good study,day day up */ public class Test { public static void main(String[] args) { MasterPerson mPerson = new MasterPerson(); Animals dog = mPerson.domateAnimals("dog"); dog.cry(); Animals cat = mPerson.domateAnimals("cat"); cat.cry(); Animals duck = mPerson.domateAnimals("duck"); duck.cry(); } }