》什么是多态
简单来说,多态(Polymorphism)是具有表现多种形态能力的特征。更专业的说法:同一个实现接口,使用不同的实例而执行不同操作。
多态的定义:值允许不同的类的对象对同一消息做出响应,就是同一消息可以根据发送对象的不同采取不同的行为方式。
多态存在的三个必要条件:
》要有继承
》要有重写
》父类引用指向子类对象
》举例说明
》父类
public abstract class Pet { protected String name="无名氏"; protected int heagth=100; //健康值 protected int love=0; //亲密度 public Pet(String name) { this.name = name; } /** * 输出宠物信息 */ public void print(){ System.out.println("宠物的自白: 我的名字叫"+this.name+",健康值是"+this.heagth+",和主人的亲密度是"+this.love+"。"); } /** * 抽象方法eat(),负责宠物吃饭功能 */ public abstract void eat(); public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHeagth() { return heagth; } public void setHeagth(int heagth) { this.heagth = heagth; } public int getLove() { return love; } public void setLove(int love) { this.love = love; }
》子类
public class Dog extends Pet{ { System.out.println("我是子类"); } private String strain; //品种 public Dog(String name,String strain) { super(name); this.strain=strain; } /** * 实现狗狗的吃饭方法 */ @Override public void eat() { super.heagth+=3; System.out.println("狗狗"+super.name+"吃饱啦!健康值增加3。"); } /** * 重写父类print()方法 */ public void print(){ super.print(); System.out.println("我是一只"+this.strain+"。"); } public void catchingFlyDisc(){ System.out.println("狗狗在玩飞盘"); } }
public class Penguin extends Pet { private String sex; public Penguin(String name,String sex) { super(name); this.sex=sex; } /** * 重写父类方法 */ public void print(){ super.print(); System.out.println("性别是"+this.sex+"。"); } /** * 实现企鹅吃饭的方法 */ @Override public void eat() { super.heagth +=5; System.out.println("企鹅"+super.name+"吃饱啦!健康值增加5。"); } public void swimming(){ System.out.println("企鹅在游泳"); } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
》主人类
public class Master { private String name; //主人名字 private int money; //元宝数 public Master(String name, int money) { this.name = name; this.money = money; } /** * 使用父类作文方法参实现多态 * 主人给宠物喂食 */ public void feed(Pet pet){ pet.eat(); } /** * 主人给Dog喂食 */ public void feed(Dog dog){ dog.eat(); } /** * 主人给 Penguin喂食 */ public void feed(Penguin pgn){ pgn.eat(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } }
》子类到父类的转换(向上转型)
public static void main(String[] args) { //主人对象 Master master = new Master("王先生",100); //通过父类引用子类对象 Pet pet = new Dog("欧欧", "雪纳瑞"); master.feed(pet); pet.print(); //pet.catchingFlyDisc(); 向上转型不能调用子类独有的方法 }
当把子类对象直接赋给父类引用变量时,例如 Pet pet = new Dog("欧欧", "雪纳瑞"); 这个pet引用变量的编译类型是 Pet ,运行时类型是 Dog,当运行时调用该引用变量的方法时,其方法行为总是表现出子类方法行为的特征,而不是父类方法的行为特征,这就可能出现:相同类型的变量、调用同一个方法时呈现出多种不同行为特征,这就是多态。
》父类到子类的转换(向下转型)
当向上转型发生后,将无法调用子类特有的方法。但是当需要调用子类特有的方法时,可以通过将父类再转换为子类来实现。将一个指向子类对象的父类引用赋给一个子类引用,称之为向下转型,此时必须进行强制类型转换。
public static void main(String[] args) { //主人对象 Master master = new Master("王先生",100); //通过父类引用子类对象 Pet pet = new Dog("欧欧", "雪纳瑞"); master.feed(pet); pet.print(); //pet.call(); 向上转型不能调用子类独有的方法 Dog dog=(Dog)pet; //强制转换成 Dog 对象 dog.catchingFlyDisc(); //调用狗狗玩飞盘方法 Penguin pgn=(Penguin)pet; //强制转换成 Penguin 对象 pgn.swimming(); //调用企鹅的游泳方法 }
结果:
把 pet 强制转换为 Dog 后,可以访问 Dog 类特有的玩飞盘方法。但必须转换为父类指向真实子类类型 Dog ,不是任意强制转换,如当转换为 Penguin类(Penguin pgn=(Penguin)pet;)时,将出现类型转换异常 ClassCastException。
如果没有转换为真实子类类型,就会出现类型转换异常。如何有效避免出现这种异常呢?Java 提供了 instanceof 运算符来进行的判断。
》instanceof 运算符
该运算符用来判读一个对象是否属于一个类或实现了一个接口。结果为 true或 false 。在强制类型转换之前通过 instanceof 运算符检查对象的真实类型,在进行相应的强制类型转换,这样就可以避免类型转换异常,从而提高代码的健壮性。
public static void main(String[] args) { //主人对象 Master master = new Master("王先生",100); //通过父类引用子类对象 Pet pet = new Dog("欧欧", "雪纳瑞"); master.feed(pet); pet.print(); //pet.call(); 向上转型不能调用子类独有的方法 if(pet instanceof Dog){ Dog dog=(Dog)pet; //强制转换成 Dog 对象 dog.catchingFlyDisc(); //调用狗狗玩飞盘方法 }else if(pet instanceof Penguin){ Penguin pgn=(Penguin)pet; //强制转换成 Penguin 对象 pgn.swimming(); //调用企鹅的游泳方法 } }
需要注意:instanceof 运算符前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系,否则会引起编译错误。