Java--面向对象之多态

       前言

        不能偷懒!不能偷懒!不能偷懒!


       多态实现条件

        1,必须在继承体系下;

        2,子类必须要对父类中方法进行重写;

        3,向上转型:父类引用指向子类对象,实现对子类对象的访问和操作。通过父类的引用调用子类中重写的父类的方法。

        4,运行时绑定:多态是在运行时确定的,而不是在编译时确定的。具体执行那个方法是根据实际指向的对象类型决定的。

        只有满足以上条件,才能实现多态性。通过多态,可以实现在不同子类对象上调用相同的方法,产生不同的行为,提高代码的灵活性和可扩展性。

什么是向上转型?

        答:将子类对象赋值给父类类型的变量,这就是向上转型。这意味着子类对象被当做父类对象来对待,只能访问父类中定义的属性和方法,而不能访问子类特有的属性和方法。这种转型可以提高代码的灵活性可扩展性,方便在不同的上下文中使用同一的接口。

        向上转型有三种实现方式:

                1,直接赋值;2,方法传参;3,方法返回。

        向上转型的缺点就是不能调用子类特有的方法。

        举个例子,假设有一个父类 Animal 和它的两个子类 Cat 和 Dog。我们可以创建一个 Cat 对象,然后将它赋值给一个 Animal 类型的变量,这就是向上转型。

  Animal animal = new Cat();

        在这个例子中,Cat 是 Animal 的子类,通过向上转型,我们将 Cat 对象赋值给了一个 Animal 类型的变量 animal。此时,animal 只能访问 Animal 类中定义的方法和属性,无法访问 Cat 类特有的方法和属性。

什么是重写?

        答:在子类里边重写父类方法,需要满足三个条件:

                1,方法名称与父类中方法名称相同;

                2,参数列表相同(参数类型、参数个数、参数顺序);

                3,返回值相同;(返回值可以不同,但必须构成协变类型

                注:如果父类方法中

                        1,是被private修饰的,那么这个方法是不能被重写的;

                        2,是static修饰的,那么这个方法是不能被重写的;

                        3,子类的访问修饰限定权限要大于等  >=  父类的修饰限定权限;

                        4,被final修饰的方法是不能被重写的;

                                final修饰变量 叫做 常量

                                final修饰类 叫做 密封类

                                final修饰方法 叫做 密封方法

                        5,要重写的方法不能是构造方法。

    

什么是协变类型:

        答:协变类型是指在类型系统中,当一个类型 A 可以被另一个类型 B 替代时,我们称 A 是 B 的协变类型。换句话说,如果一个函数或方法接受类型 B 的参数,那么它也能接受类型 A 的参数,而不需要进行特殊的转换或处理。

        在面向对象编程中,协变类型通常与继承关系有关。如果一个类 B 继承自类 A,且 B 是 A 的子类型,那么我们可以说 B 是 A 的协变类型。这意味着可以将类型 A 的对象用作类型 B 的对象,而不会引发类型错误。

        更具体地说,对于协变类型来说,可以将子类型的实例赋值给父类型的引用变量,而不会导致编译错误。这是因为子类型中的方法和属性是父类型的超集,可以直接进行访问。

        例如,在Java中,如果类 B 继承自类 A,且 A 是一个接口,那么我们可以将 B 的实例赋值给 A 类型的引用变量。这是因为接口的实现类对于接口来说是协变类型。

        总之,协变类型使得父类型的引用可以指向子类型的对象,提供了更大的灵活性和可重用性。

        

        当谈论协变类型时,我们可以考虑一个经典的例子——关于动物和狗的层次结构。假设有一个 Animal 类和一个 Dog 类,Dog 是 Animal 的子类。

        在这种情况下,我们可以将一个数组或列表视为协变类型。假设我们有以下代码:

class Animal {}
class Dog extends Animal {}

public class Main {
    public static void main(String[] args) {
        // 创建一个 Animal 类型的数组
        Animal[] animals = new Animal[2];
        
        // 将 Dog 对象添加到数组中
        animals[0] = new Dog();
        
        // 协变:将 Animal[] 类型引用赋值给更具体的 Dog[] 类型引用
        Dog[] dogs = (Dog[]) animals;
        
        // 访问数组中的元素,这时会抛出 java.lang.ArrayStoreException 异常
        // 原因是我们将 Animal 对象存储在了 Dog 数组中
        System.out.println(dogs[0]);
    }
}

        在上面的例子中,我们创建了一个 Animal 类型的数组,并且将 Dog 对象存储在其中。然后,我们使用协变(通过强制类型转换)将 Animal[] 类型的引用赋值给更具体的 Dog[] 类型的引用。尽管编译器允许这样做,但在运行时会抛出 java.lang.ArrayStoreException 异常。这是因为我们将一个 Animal 对象存储在了 Dog 数组中,而 Dog 数组只能存储 Dog 对象。

        


        我是专注学习的章鱼哥~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值