首页 > 其他分享 >面向对象---多态的基础语法

面向对象---多态的基础语法

时间:2022-09-20 11:13:25浏览次数:67  
标签:instanceof 子类 move 多态 Cat --- 面向对象 Animal Bird

多态的基础语法
Q:什么是多态?
A:多种形态,多种状态。

学习多态基础语法之前,我们需要普及两个概念。

注意---java中允许向上转型,也允许向下转型
无论是向上转型,还是向下转型,
两种类型之间必须有继承关系,没有继承关系就会报错。

1、向上转型
子--->父(自动类型转换)

2、向下转型
父--->子(强制类型转换,需要加强制类型转换符)

什么时候必须向下转型?
不能随意做强制类型转换,只有当你想访问的是子类对象中“特有”的方法,此时必须进行向下转型。
强制类型转换符:(子类名)

理解两种转型
向上转型:
父类 =new 子类;(表示子类对象被转化为了父类对象)
(1)子类中重载的方法会覆盖父类中的方法;(方法覆盖)这就是动态连接
(2)而子类中单独存在的方法无法调用; (方法丢失)
也就是说:向上转型时,子类只能重载并覆盖父类的方法,除此之外没有其他方法了(暂时先这么理解)。

向下转型:
向下转型的前提是必须先向上转型(但一定是要转回与之前一样的类型,不能转成了其他类型,这样子会报错)
(1)个人的理解就是为了解决向上转型时 ,子类中单独存在的方法会丢失的现象,经过又一次的向下转型转回来了,子类中那些单独存在的方法也就能用了;
(2)一定是要转回与之前一样的类型,不能转成了其他类型,这样子会报错。

多态指的是
父类型的引用指向子类型对象。
包括编译阶段和运行阶段,
编译阶段:静态绑定父类的方法;
运行阶段:动态绑定子类型的对象的方法。
多种形态。

点击查看代码
//动物类,父类
public class Animal {
    public void move(){
        System.out.println("动物在移动!!");
    }

//鸟类,子类
public class Bird extends Animal{
    //重写move()方法
    public void move(){
        System.out.println("鸟儿在飞翔!!");
    }
    public void sing(){
        System.out.println("鸟儿在歌唱!!");
    }
}
//猫类,子类
public class Cat extends Animal {
    //重写move()方法
    public void move(){
        System.out.println("猫在走猫步!!");
    }

    //猫除了move之外,应该有自己特有的行为,例如--抓老鼠
    //这个行为是子类特有的方法
    public void catchMouse(){
        System.out.println("猫在抓老鼠!!!");
    }
}
多态的基础语法 父类型的引用指向子类型的对象。 向下转型的前提---必须要有向上转型
点击查看代码
public class Test01 {
    public static void main(String[] args) {
        Animal a1 = new Animal();
        Cat c1 = new Cat();
        Bird b1 = new Bird();
        a1.move();//动物在移动!!
        c1.move(); //猫在走猫步!!
        b1.move();//鸟儿在飞翔!!

代码可以这样写吗?
/**
* 1、Animal和Cat之间有继承关系吗?---有
* 2、Animal是父类,Cat是子类
* 3、Cat is a Animal,这句话能不能疏通?---能
* 4、经过测试得知,java中支持这样的一个语法
* 父类型的引用允许指向子类型的对象.
*/

    //向上转型
    Animal a2 = new Cat(); //a2就是父类型的引用,new Cat()是一个子类型对象,允许a2这个父类型引用指向子类型对象
    Animal a3 = new Bird();
    //调用a2的move()方法
    
    /**
     * 什么是多态?
     *   多种形态,多种状态。
     * 注意:为什么没有输出Animal中的“动物在移动”,而是输出子类中重写后的move()方法?
     * (即: 编译阶段只知道a2的类型是Animal,编译通过;运行时是底层对象在移动,也就是Cat在移动。真正负责移动的是对象。)
     
     * 分析:a2.move()
     *      java程序分为编译阶段和运行阶段
     *      1、先来分析编译阶段--
     *         对于编译器来说,编译器只知道a2的类型是Animal,
     *         所以编译器在检查语法的时候,会去Animal.class字节码文件中找move()方法,
     *         找到后,绑定move()方法,编译通过,静态绑定成功。(编译阶段属于静态绑定)
     *      2、再来分析运行阶段--
     *          运行阶段,实际上在堆内存中,创建的java对象是Cat对象,
     *          所以move的时候,真正参与move的对象是一只猫,
     *          所以运行阶段会动态执行Cat对象的move方法。
     *          这份过程属于动态绑定(运行阶段绑定属于动态绑定)
     *      3、何来多态?
     *          多态表示多种形态,编译的时候是一种形态,运行的时候是另一种形态。
     *          因此叫多态。
     *         */
    a2.move(); //猫在走猫步!
    //调用a3的move()方法
    a3.move(); //鸟儿在飞翔!!

    前提:在猫类中写了独有的catchMouse()方法
    Animal a5 = new Cat(); //底层对象是一只猫

    //分析这个程序能否编译和运行?
    //分析程序一定要分析编译阶段的静态绑定和运行阶段的动态绑定
    //只有编译通过的代码才能运行,没有编译通过,根本轮不到运行
    //a5.catchMouse();  //编译器报错
    //因为编译器只知道a5的类型是Animal,去Animal.class文件中找catchMouse()方法中找,结果没有找到,静态绑定失败,编译报错,无法运行。
    //编译器只看等号左边!!!!!!!!

    /**
     * Q:假设代码写到这里,非要调用catchMouse()方法怎么办?
     * A:必须用到“向下转型”(强制类型转换)
     *  Q:以下这行代码为什么没有报错?
     *  A:a5是Animal类型,转成Cat,Animal和Cat之间存在继承关系,所以没有报错*/
    Cat x = (Cat)a5;
    x.catchMouse();

    //向下转型有风险吗?
    Animal a6 = new Bird();
    /**
     * Q:分析以下程序,编译报错还是运行报错?
     * A:编译器检测到a6这个引用是Animal类型,而Animal和Cat之间存在继承关系,所以可以向下转型。编译没有出错。
     *    运行阶段,堆内存实际创建的对象是---Bird对象,
     *            在运行过程中,拿着Bird对象去转换成Cat对象就不行了
     *            因为Bird和Cat之间没有继承关系。
     *
     
     * 运行时出现异常,这个异常和空指针异常一样非常重要:
     *      java.lang.ClassCastException : 类型转换异常
     *      java.lang.NullPointException : 空指针异常
     *        Cat y = (Cat)a6;
     *        y.catchMouse();
     *
     * Q:怎么避免ClassCastException异常的发生??
     * A: 利用运算符
     *       instanceof(运行阶段动态判断)
     *     第一:instanceof可以在运行阶段动态判断引用指向的对象的类型;
     *     第二:instanceof的语法
     *              (引用 instanceof 类型)
     *     第三:instanceof运算符的运算结果只能是---true/false
     *     第四:c是一个引用,c变量保存了内存地址,指向了堆中的对象。
     *               假设(c instanceof Cat)为true表示:
     *                   c引用指向的堆内存中的java对象是一个Cat。
     *               假设(c instanceof Cat)为false表示:
     *                   c引用指向的堆内存中的java对象不是一个Cat。
     * 程序员要养成一个好习惯--
     *   任何时候,任何地点,对程序向下转型的时候,一定要使用instanceof运算符进行判断。
     *   这样可以很好的避免:ClassCastException
     *         */
点击查看代码
   System.out.println(a6 instanceof Cat);  //结果为false
        if (a6 instanceof Cat) { //如果a6是一只Cat
            Cat y = (Cat)a6;  //再进行强制类型转换
            y.catchMouse();
        }
    }
}

package dt; /** *防止读不懂代码,必须向下转型 * */
点击查看代码
public class Test02 {
    public static void main(String[] args) {
        Animal x = new Bird();
        Animal y = new Cat();

        if(x instanceof Bird){         //必须要通过instanceof判断
            Bird b = (Bird)x;
            b.sing();
        } else if (x instanceof Cat) {
            Cat c = (Cat)x;
            c.catchMouse();
        }

        if(y instanceof Bird){
            Bird b = (Bird)y;
            b.sing();
        } else if (y instanceof Cat) {
            Cat c = (Cat)y;
            c.catchMouse();
        }
    }
}

标签:instanceof,子类,move,多态,Cat,---,面向对象,Animal,Bird
From: https://www.cnblogs.com/sevenxx/p/16710372.html

相关文章

  • 2022.9.20 1005-1008
    1005#include<stdio.h>#include<stdlib.h>#include<math.h>intmain(){unsignedlonglongn;scanf("%llu",&n);unsignedlonglongm=(unsignedlonglong......
  • vue 使用element-ui 需要配置的东西
    在vue中输入npmielement-ui-S进行安装  在这个文件中配置  就可以在vue中使用element-ui......
  • Three-js入门3-插件stats和dat-GUI.md
    title:Three.js入门3-插件stats和dat.GUIcopyright:truepermalink:8top:0date:2019-01-2702:42:55tags:['three']categories:techpassword:翻译自官方文......
  • 大数据面试每日一题-Kafka为什么这么快?
    Kafka为什么这么快?1.kafka是基于partition 分区技术实现的,分布式提高Kafka的并发量2.KafKa的稀疏索引机制,kafka每4kb插入一个索引,索引在查询时候,可以比较高的效率查到到......
  • 第十一章 Ansible-playbook变量注册和Facts缓存
    一、变量注册概述当absible的模块在运行之后,其实都会返回一些result结果,就像是执行脚本,我们有的时候需要脚本给我们一些return返回值,我们才知道,上一步是否可以执行成功,但......
  • RS3MB-ASEMI高效二极管RS3MB
    编辑:llRS3MB-ASEMI高效二极管RS3MB型号:RS3MB品牌:ASEMI封装:SMA-F正向电流:3A反向电压:1000V引线数量:2芯片个数:1芯片尺寸:84MIL漏电流:<5ua恢复时间:150~500ns浪涌电......
  • 第十章 Ansible-playbook变量基础
    一、ansible变量概述ansible变量提供了便捷的方式来管理Ansibleplaybook的每一个项目中的动态值,比如nginx-1.6.3这个软件包的版本,在其它地方或许会反复使用,那么如果讲此......
  • 确定有mono-libgdiplus包,但Homebrew找不到?
    引言brewinstallmono-libgdiplus找不到包。搜索类似报名、搜索已经删除的包、搜索github都找不到。Warning:Noavailableformulawiththename"mono-libgdiplus".......
  • 前端-VUE实现第三方登录
    实现流程点击第三方登录按钮:执行window.open方法,打开一个第三方指定url出口,该地址会指向第三方登录url,并且由第三方提供一个对应的二维码弹出一个小窗口,展示对应二维码:......
  • node.js 使用教程-3.gulp-file-include 详细教程
    前言gulp-file-include是gulp插件,它提供了一个include方法让我们可以像后端模板那样把公共部分的页面导入进来,实现html复用。环境准备gulp-file-include是gulp的......