面向对象三大特性之一 多态

多态的含义

  • 同一个对象,在不同时刻表现出来的不同形态

多态的前提和体现

  • 有继承或实现关系
  • 有方法的重写
  • 有父类引用指向子类对象, 接口的引用指向是实现类的对象

多态的成员访问特点

  • 构造方法
    • 和继承一样,每个构造方法默认第一行都会有super()去访问父类的无参构造, 当然这建立在你没有手动添加super()方法
  • 成员变量
    • 编译看父类,执行看父类
  • 成员方法
    • 编译看父类,执行看子类(子类的方法包括继承父类的方法)
public class Test02 {
    public static void main(String[] args) {
        Father f = new Son();

        /*对于成员变量而言,无论是编译还是运行,都只看对象初始化时的左边(也就是父类)*/
        System.out.println(f.a); // 30 由此可见其访问的是父类的变量
        //System.out.println(f.b); 因为父类中没有该变量
        
        /*对于成员方法而言,编译看左边(父类),执行看右边(子类)*/
        // f.method(); 报错 因为父类没有这个方法,在编译阶段就报错了
        f.show(); // 子类的show()方法 由此可见其执行的是子类的show()方法
    }
}

class Father {
    int a = 30;

    public void show() {
        System.out.println("父类的show()方法");
    }
}

class Son extends Father {
    int a = 10;
    int b = 20;

    @Override
    public void show() {
        System.out.println("子类的show()方法");
    }

    public void method() {
        System.out.println("子类的method()方法");
    }
}

优缺点

  • 多态的优点: 提高代码的扩展性
    • 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象
    • 定义方法的时候使用父类作为方法的返回值类型 , 该方法可以返回此父类任意子类对象
    • 定义变量时 , 用父类类型变量接收子类类型对象
  • 多态的缺点: 不能访问子类的特有成员

多态的转型

  • 向上转型: 把子类类型的对象赋值给父类类型变量 Father f = new Son();
  • 向下转型: 把父类类型的数据赋值给子类类型的变量 Son s = (Son)f;
    • 优点: 解决多态中不能调用子类特有成员的弊端
public abstract class Animal {
    public abstract void eat();
}

class Dog extends Animal {

    @Override
    public void eat() {
        System.out.println("狗吃肉");
    }

    public void lookHome() {
        System.out.println("狗看家");
    }
}

class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }

    public void catchMouse() {
        System.out.println("猫抓老鼠");
    }
}

class Pig extends Animal {

    @Override
    public void eat() {
        System.out.println("猪拱白菜");
    }

    public void sleep() {
        System.out.println("猪特别能睡");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型

        useAnimal(new Dog());
        useAnimal(new Cat());
        useAnimal(new Pig());
    }

    public static void useAnimal(Animal animal) {
        animal.eat();
        if(animal instanceof Dog){
            Dog dog = (Dog) animal; // 向下转型
            dog.lookHome();
        }else if(animal instanceof Cat){
            Cat cat = (Cat) animal; // 向下转型
            cat.catchMouse();
        }else if(animal instanceof Pig){
            Pig pig = (Pig) animal; // 向下转型
            pig.sleep();
        }
    }
}

/*
执行结果:
狗吃肉
狗看家
猫吃鱼
猫抓老鼠
猪拱白菜
猪特别能睡
*/

多态转型注意点

  • 如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
public class Test3 {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        Dog dog = (Dog) animal; // 向下转型

        // 报错: ClassCastException 原因是该animal的本质是狗,
        // 你可以说它是动物,但却不能说它是猫
        Cat cat = (Cat) animal; 
    }
}

解决转型安全隐患

  • 关键字 :  instanceof
  • 使用格式:
    • 象名 instanceof 引用数据类型
    • 通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
public class Test3 {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型
        Dog dog = (Dog) animal; // 向下转型
        System.out.println(animal instanceof Animal); // true
        System.out.println(animal instanceof Dog); // true
        System.out.println(animal instanceof Cat); // false
    }
}
  • 可以看出由Dog对象向上转型成为Animal对象的animal,本质上属于Dog类和Animal类,并不属于Cat类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值