Java——多态

news2024/12/23 23:38:23

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

神奇的多态

  • 什么是多态?
  • 重写
  • 向上转型和动态绑定
  • 向下转型
    • instanceof

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

什么是多态?

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

重写

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

    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类型的引用,而我们传的确实它的子类对象,接着我们通过父类引用调用子类中重写的方法,在运行时发生动态绑定,最终的效果就是我们的方法完全一样,只是因为传参的不同,就呈现出了不同的形态,这就是我们说的多态!
好了,那么关于多态的重点知识大概也就这么多了,自由的感觉真好,希望大家也要好好学习啊!
百年大道,你我共勉!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150554.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[oeasy]python0041_ 转义字符_转义序列_escape_序列_sequence

转义序列 回忆上次内容 上次回顾了5bit-Baudot博多码的来历从 莫尔斯码 到 博多码 原来 人 来 收发电报 现在 机器 来 收发电报 输入方式 从 电键改成 键盘 输出方式 从 纸带变成 打印纸张 后来 电传打字机ASR-33成为 初代 经典终端 除了 \n 和 \r 之外 还有什么 特殊字符 吗…

前端格式化工具使用(eslint、stylelint、prettier、lint-staged和husky搭配格式化代码)

目录 eslint 安装eslint .eslintrc.js env extends parser parserOptions rules globals plugins 屏蔽eslint检测具体规则 官方规则 stylelint 安装stylelint 创建stylelint配置文件 .eslintrc.js extends sass文件的格式检查 prettier 安装使用prettier …

Vue组件-插槽

一、插槽 1. 组件的三大核心:属性(data、props)、事件、插槽 2. 插槽(slot) 插槽(slot)将父组件的内容与子组件的模板相混合,从而弥补了视图的不足。 插槽的目的:使组件…

ConstraintLayout2

ConstraintLayout2ImageFilterView 属性 app:altSrc:altSrc提供的资源将会和src提供的资源通过crossfade属性形成交叉淡化效果。默认情况下,crossfade0,altSrc所引用的资源不可见,取值在0-1app:saturation:float型,默认1&#xf…

FPGA知识汇集-时钟系统的移植

ASIC 和FPGA芯片的内核之间最大的不同莫过于时钟结构。ASIC设计需要采用诸如时钟树综合、时钟延迟匹配等方式对整个时钟结构进行处理,但是 FPGA设计则完全不必。因为后者有内建的时钟资源:锁相环、频率综合器、移相器,以及具有低延迟特性的专用时钟布线网…

Unity基于状态机的架构与设计

我们做游戏的时候经常会有流程控制,流程控制的方法有很多,行为决策树,状态机等。本质差别都不大,就是把每一段执行逻辑做成一个一个的节点,根据条件执行某个节点,切换到某个节点。今天给大家分享一下基于状…

如何在VSCode中添加Python解释器并安装Python库

如何在VSCode中添加Python解释器并安装Python库作者介绍一. 安装VScode编辑器二. 安装Python解释器三. 在VScode中添加Python解释器四. 创建项目并在VScode中打开;五、在VScode中安装Python库作者介绍 孟莉苹&#xf…

【TypeScript入门】TypeScript入门篇——对象

对象其实就是一种封装的概念,它把事物封装成一个类,然后提供类的接口,而具体的过程人们是看不到的。 一、对象实例 二、TypeScript 类型模板 三、鸭子类型(Duck Typing) 对象是包含一组键值对的实例。 值可以是标量、函数、数组、对象等&am…

Linux常用命令——lsof命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) lsof 显示Linux系统当前已打开的所有文件列表lsof -p pid 补充说明 lsof命令用于查看你进程打开的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系…

十四、Node.js 中 session验证登录

在前一篇内容中讲到这个cookie实现验证登录,cookie是存储在客户端的,而session是存储在服务器的,相比较session的安全性会更高,session对象存储特定用户会话所需要的属性以及配置信息,服务通过session对象将用户的信息…

CPU使用率过高的原因及解决方法

常见的CPU使用率过高可不是职场CPU哦,而是电脑的中央处理器,CPU作为计算机系统重要的运算和控制核心,可谓是“很忙”的存在。在我们日常使用电脑设备时,由于打开的软件、游戏、网页等程序容易导致电脑运作卡顿,这时候就…

《图机器学习》-Traditional Methods for Machine Learning in Graphs

Traditional Methods for Machine Learning in Graphs前言一、Node-Level Tasks and Features二、Link-Level Tasks and Features三、Graph-Level Tasks and Features前言 图机器学习任务可以分为三种: Node-level prediction:节点级的预测 如对节点进…

最优控制学习笔记3----无约束条件的泛函极值问题

无约束条件的最优控制问题 设函数 x(t)x(t)x(t) 在 [t0,tf][t_0, t_f][t0​,tf​] 区间上连续可到,考虑 Lagrange型性能指标函数 J[x(t)]∫t0tfL[x(t),x˙(t),t]dtJ[x(t)]\displaystyle\int_{t_0}^{t_f}L[x(t), \dot{x}(t), t]dtJ[x(t)]∫t0​tf​​L[x(t),x˙(t),…

Linux---常见指令

目录 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令 06.rmdir指令 && rm 指令 07.man指令 08.cp指令 09.mv指令 10. cat指令 11.more指令 12.less指令 13.head指令 13.tail指令 简述重定向和管道概念: 14.时间相关的指令 15.Ca…

Git Fork操作与配置

我理解的git fork:将别人(张三)仓库包括文件,提交历史,issues等复制一份到自己的github账号下。我们在可以通过修改本地项目的代码,然后,给(张三)发送一个Merge Request&…

C. Yet Another Tournament(贪心)

Problem - C - Codeforces 通用领域 医学 计算机 金融经济 你正在参加另一场比赛。有n1个参与者:你和其他n个对手,编号从1到n。 每两名参与者将相互竞争一次。如果对手i和对手j比赛,他获胜当且仅当i>j。 当我的对手和你对弈时,一切都变…

rabbitmq+netcore6 【4】Routing:路由

文章目录1)前言2)Direct exchange 直接类型的交换机3)Multiple bindings 多绑定4)Emitting logs 发送日志5)Subscribing 订阅6)综合以上代码准备工作生产者消费者1消费者2消费者3运行结果官网参考链接&…

USB大容量存储设备浅析

一 USB 设备类 SB 引入了设备类的概念,根据每一类驱动程序的功能将USB设备分为几大类,标准的几大类包括: 大容量存储类 网络类 集线器类 串行转换器 音频类 视频类 图像类 调制解调器 打印机 HID(Human Interface Device 人机接口设备)每一…

我记不住的那些编程语言的语法(数组)-1

背景:我记不住各种语言的语法,例如C、Java、Go、Python、JavaScript,大概就是常用的这几种语言,每种语言有其自己的语法规范,有的时候会记混了,所以想记录一下细节。这个系列会不定期的更新,本期…

一路坎坷,入局到突破【2022年度总结】

秃秃 1> 来到CSDN: 2019年5月时决定只身一人去外省实习,顺便在CSDN这个“资源库”注册了一下账号。直到我20年在公司做技术分享时,才真正开始在CSDN上的创作; 21年的时候也只是把CSDN当做笔记,就自己写一写&…