Java——多态

文章详细解释了Java中的多态性,包括重写的概念,如何通过向上转型实现多态,并介绍了动态绑定的作用。文中还讨论了重写的方法必须具有相同的函数名、返回类型和参数列表,并强调了private、static、final方法不能被重写。此外,文章展示了向下转型的风险,并使用instanceof关键字作为安全检查。最后,通过一个例子展示了多态在实际编程中的应用。
摘要由CSDN通过智能技术生成

好久不见啊,兄弟们!!这不将近期末考试了吗,阿涛平日里课听的不多,所以最近都在疯狂补课,祖宗之法也可变,阿涛的学校终于不是二十周校历了!!希望从今往后我们的生活都能够回归正轨吧!

面向对象的三大特性:封装、继承、多态。封装和继承我们已经在之前的博客中进行了一定的说明,今天我们站好最后一班岗,讲一讲多态!

什么是多态?

我觉得初学多态可以从字面上来理解:面向不同的对象时,会有多种形态。

重写

之前我们讲重载的时候,提过两者之间的差别,我们来复习一下。
重载是在同一个类中(或者继承关系),对于方法我们需要不同的返回类型(重载对于返回类型不做要求,甚至于可以没有返回类型),参数列表(类型个数顺序):

    public int add(int a,int b){
        return a+b;
    }
    public int add(int a){
        return a;
    }
    public double add(double a,int b){
        return a+b;
    }

方法名相同的方法之间,不同的仅仅是参数列表和返回类型,这些方法之间构成了重载,也就不需要我们程序猿额外进行大量无意义的记忆。
那么重写是什么呢?

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void eat(){
        System.out.println(this.name+"eating");

    }
}
public class Dog extends Animal{

    public int height;
    public void eat(){
        System.out.println(this .name+"恰狗粮");
    }
    public Dog(String name,int age){
        this.name=name;
        this.age=age;
    }
    public Dog(){

    }
}

在这里插入图片描述
本来我是想在一个.Java文件下面写的,但是后来发现最好还是一个类写成一个Java文件好一点。
我们来分析一下:Dog这个类继承了Anima这个类,那么Anim类中非静态的属性、方法都会被Dog继承,本来在Animal类中有eat方法,但是我们在Dog类中重写了这个方法,那么下面我们测试的时候调用的就是我们在Dog里面写的这个方法。
那么重写一般用于继承关系中,在子类中重写父类已有的方法,重写的方法函数名、返回类型、参数列表都要一样,不然怎么能叫做重写呢?
关于重写我还有几点想强调一下:
1.关于重写的两个方法,他们的返回类型必须相同或者退而求其次,必须是父子类关系,构成协变类型。
2.在子类中重写的方法,其访问权限必须大于父类方法的访问权限!
3.private、static、final修饰的方法不可以被重写:
private:被private修饰的只能在当前类中使用,出了父类在子类中怎么能够使用呢?
static:被static修饰的静态方法就就是类方法了,就不属于对象的了,而重写基本上就是为了多态服务的,多态是面向对象的三大特性,现在类方法甚至都不需要对象了,那我们不就是瞎忙活了嘛?
final:被final修饰的变量是常变量,被final修饰的引用不可以指向其他的引用,被final修饰的方法不可以被重写!

向上转型和动态绑定

想要发生多态,向上转型和动态绑定是基础。
在这里插入图片描述
一般来说,我们习惯于把父类放在上面,基础这个普遍认识,我们说的向上转型就是把一个子类对象赋值给一个父类引用,或者说,就是使用父类引用引用子类对象!
在这里插入图片描述
在第一行就发生了我们所说的向上转型,可是为什么第二行报错了呢?我们明明在Dog类中定义了height这个成员变量啊!animal也确实是指向我们new出来的Dog对象啊!
在这一点上我们可以这样理解:无论anima指向谁,它始终是一个Animal类型的引用,那么它就只可以使用Animal中的字段和方法!
在这里插入图片描述
此时此刻兄弟们或许还是没有意识到我这张图片的用意。如果是刚才我们说的animal这个引用只可以访问Animal类中的方法,那么为什么此时此刻我们打印出来的是Dog中的eat方法呢?
这就是我们多态实现的第二个基础:动态绑定。
也就是说在编译期间我们调用的确实是animal的eat方法,但是在运行期间,会发生动态绑定,绑定到我们的Dog对象的eat方法。

向下转型

有了向上转型相应的我们也就会有向下转型,通过类比思想,不难总结出向下转型就是通过子类引用引用父类对象:
在这里插入图片描述
这里报错的原因是因为类型不匹配,我们可以很轻易的把一个子类对象赋值给一个父类引用,因为小狗本身就是动物,但是我们怎么敢说每一个动物都是小狗呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过这一系列的操作,这下子从效果上来说我们的dog引用此时就指向了一个Dog对象,那么我们就可以通过dog引用访问Dog对象中的字段和方法了。
但是这样子的向下转型是有大的风险的:

        Cat cat=new Cat("gzj",20);
        Animal animal=cat;
        Dog dog=(Dog)animal;

兄弟们且来看这串代码,在编译器看来这是没有问题的,但是我们细细分析,最终的效果就是我们用了一个Dog类型的引用指向了一个Cat对象,这合理吗?这显然是不行的:
在这里插入图片描述
只要一运行,这个程序的遮羞布就会被薅下来,程序的丑陋就会一览无余,那我们就想啊,能否在向下转型的时候进行一定的检查呢?诶,我们还真有:

instanceof

        Cat cat=new Cat("gzj",20);
        Animal animal=cat;
        if(animal instanceof Dog) {
            Dog dog = (Dog) animal;
            dog.eat();
        }else{
            System.out.println("不匹配");
        }

在这里插入图片描述
只有当animal指向Dog类型的时候我们才可以进行向下转型。

关于多态的知识点差不多就这么多了,最后呢,阿涛想给兄弟们看一下多态的一个小小的使用:

    public static void shout(Animal animal){
        animal.bark();
    }
    public static void main(String[] args) {
        shout(new Dog());
        shout(new Cat());
        shout(new Wolf());

在这里插入图片描述
我们的Dog、Cat、Wolf三个类都继承了Animal类并且重写了其中的bark方法,接着通过传参我们就实现了向上转型:shout方法的参数是Anima类型的引用,而我们传的确实它的子类对象,接着我们通过父类引用调用子类中重写的方法,在运行时发生动态绑定,最终的效果就是我们的方法完全一样,只是因为传参的不同,就呈现出了不同的形态,这就是我们说的多态!
好了,那么关于多态的重点知识大概也就这么多了,自由的感觉真好,希望大家也要好好学习啊!
百年大道,你我共勉!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值