》什么是多态

  简单来说,多态(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("宠物的自白:\n我的名字叫"+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 运算符前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系,否则会引起编译错误。

 

 posted on 2017-08-08 16:16  【邵江】  阅读(276)  评论(0编辑  收藏  举报