面向对象基础-多态

多态的引入(polymorphic)

什么是多态?

  • 某同一个事物,在不同的时刻表现出不同的状态

    • 对于Java而言,指的是同一个类型引用,在指向不同的具体对象时,运行时表现不同的行为

    • 其实就是父类引用指向了不同的子类对象

    • 例如

      • Animal a = new Cat();
        Animal a = new Dog();
        
  • 多态的前提条件

    • 要有继承关系
    • 继承后发生子父类的方法重写
    • 父类的引用指向子类的对象
      在这里插入图片描述
  • 不能发生多态的情况

    • 不能够被继承,final类
    • 不能被方法覆盖
      • final方法
      • static方法
      • private方法
      • 构造方法
  • 当父类的引用,指向不同的实际对象时,调用方法,结果不同

  • 写一个方法,参数列表为父类引用,可以传入具体的对象

    • 多态对程序的扩展性

多态的访问特点

在这里插入图片描述

发生多态后,通过引用调用成员的方式发生了改变

父类 引用 = new 子类();

  • 对于成员变量而言

    • 编译时看左边,运行时看左边
    • 也就是说成员变量是没有“多态”的(因为多态的前提就是发生方法重写)
    • 多态现象是发生在方法之间,和成员变量没有关系
  • 对于成员方法而言

    • 编译时看左边,运行时看右边
      在这里插入图片描述
  • 编译看左边

    • 编译看左边是说通过引用变量可以访问到的子类成员的范围
      • 是由引用类型来决定的,也就是说由父类中定义的成员决定
    • 我们只能通过引用去访问堆上的对象,引用中必然装有该类型对象的成员信息
    • 只有通过引用变量,我才能访问到堆上的对象
      • 也就是说,对象的访问受限于引用变量本身的类型

解释方法的多态性,一个很贴切的例子

  • 我家中的一台电视机,贼贵,功能很丰富
  • 对于电视机而言,我们只能使用,遥控器去操作电视机
  • 这也就是说,只有遥控器上提供的功能我们才能使用
    • 即便电视机本身功能多么强大,如果遥控器上只有音量键,那我们也毫无办法
    • 遥控器有啥功能,决定了我们能使用的功能
  • 即使电视机本身功能再丰富,没有遥控器的支持,我们啥也用不了

把这个例子转换到Java程序中

  • 电视机就相当于对象本身,而遥控器就是引用变量
  • 实际对象的功能再强大,如果引用中没有这个功能,那也无法调用该功能
  • 对象的行为,受限于引用变量,和对象本身没有直接关系
  • 对象的引用类型决定了可以访问对象的成员范围
  • 编译时看左边,运行时看右边

解释成员变量不具有多态性,一个例子

  • 成员变量描述的是对象的“外貌特征”
  • 把子类对象赋值给父类类型的引用,就相当于给子类对象披上了一个父类类型马甲
  • 外貌特征上来看,这时候的子类就变成了父类
  • 编译时看左边,运行时看左边

多态的优缺点

在这里插入图片描述

  • 多态的优点:

    • 要实现多态,必须要继承,提高了程序的可维护性(继承保证)
    • 发生多态后,同一个引用调用方法产生不同的行为
      • 提高了程序的简洁性和扩展性(多态保证)
  • 多态的缺点:

    • 不能访问子类特有的功能

在这里插入图片描述
在这里插入图片描述

多态中的转型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本数据类型之间是可以发生数据类型转换的,引用数据类型也是可以的

但是引用数据类型发生转换的条件比较苛刻,出错后的问题也更严重

引用数据类型要发生类型转换

  • 前提:具有父子关系的两个类型之间
  • 没有父子关系的两个类型之间不能发生类型转换,通过不了编译

多态中的转型内存图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多态实现猫和狗案例

在这里插入图片描述
Animal

public class Animal {
    private String name;
    private int age;

    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void eat() {
        System.out.println("动物吃东西");
    }
}

Cat

public class Cat extends Animal {

    public Cat() {
    }

    public Cat(String name, int age) {
        super(name, age);
    }

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

Dog

public class Dog extends Animal {

    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }

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

AnimalDemo

/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建猫类对象进行测试
        Animal a = new Cat();
        a.setName("加菲");
        a.setAge(5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

        a = new Cat("加菲", 5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

    }
}

在这里插入图片描述

自动类型转换

  • 子类的引用转换成父类的引用,在继承链中属于向上,编译器默认允许

    • 称之为自动类型转换或者向上转型

    • 语法

    • 父类 引用名 = new 子类();
      
    • 子类一定可以看成父类,所以能够自动转型

    • 向上转型是安全,可以放心使用

强制类型转换

  • 父类的引用转换成子类的引用,在继承链中属于向下,编译器默认不允许,需要显式强行转换

    • 称之为强制类型转换或者向下转型

    • 语法

    • 子类 引用名 = (子类)父类引用;
      
    • 子类继承和扩展了父类,父类大多数情况下都不能看成子类,所以需要强制类型转换

    • 重要前提:强制类型转换若想成功,必须是该父类引用指向的对象本身就是一个要强转的子类对象

  • 强制类型转换是不安全的,要想转型成功,必须真实的对象和要转型的类型一致

    • 父类引用指向的不一定就是那个你要强转的子类的对象
    • 比如动物类的引用指向了一个猫对象,现在把引用强转成一个狗引用,能成功吗?
  • 为了保障安全,向下转型推荐使用instanceof关键字校验

    • 语法

    • 引用名 instanceof 类名
      
    • 这个表达式返回一个布尔类型的值

      • true代表该引用指向的对象,是一个后面类名的对象
      • null instanceof 任何类 结果都是false

ClassCastException

强制类型转换一旦失败,就会抛出ClassCastException,程序报错终止

  • 没有人会故意给自己找麻烦
  • 不到万不得已,不要使用强制类型转换
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值