初识JAVA-面向对象的三大特征之多态

1. 重温面向对象

面向对象是一种解决问题的思想,它把计算机程序看作是各种对象组合起来的。每个对象都有自己的数据(属性)和行为(方法),主要依靠对象之间的交互来解决和实现问题。Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。

2. 多态

2.1 多态的概念

多态,简单来说就是多种形态,复杂点说就是不同对象去完成某个行为时产生不同的状态。

总的来说:同一件事情,发生在不同对象上,就会产生不同的结果。

2.2 多态实现条件

Java中实现多态,必须满足以下的条件,缺一不可:

1. 必须在继承的体系下才可以实现多态

2. 子类必须要对父类方法机械能重写

3. 通过父类的引用调用重写的方法

父类:

public class Pet{
    String name;
    String species;

    public Pet(String name, String species) {
        this.name = name;
        this.species = species;
    }
    public void eat(){
        System.out.println(name+"在进食");
    }
}

子类:

public class Cat extends Pet{
    public Cat(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃冻干");
    }
}
public class Dog extends Pet{
    public Dog(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮");
    }
}

进行测试:

public class TestPet {
    public static void eat(Pet pet){
        pet.eat();
    }
    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        eat(cat);
        eat(dog);
    }
}

TestPet的代码时类调用者的编写

当类的调用者在编写eat这个方法时,参数类型为Pet(父类),此时在该类方法内部并不知道,也不关注当前的pet引用指向的那个子类的实例,pet这个引用调用的eat方法就可能有多种不同的表现(和pet引用的实例相关),这种行为就成为多态。

2.3 重写

重写(Override):也称为覆盖。重写是子类对父类非静态,非private修饰,非fianl修饰,非构造方法等的实现过程进行重新编写,返回值和形参都不能改变(外表不变,内心改变)。重写的好处在于子类可以根据需要,定义特定于自己的行为。

方法重写的规则:

1. 子类在重写父类方法时,必须与父类方法的方法名,参数列表要完全一致

2. 被重写的方法返回值类型可以不同,但是必须是具有父子关系的

3. 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类方法被public修饰,则子类中重写该方法就不能声明为protected

4. 父类被static,private修饰的方法,构造函数都不能被重写

5. 重写的方法,可以使用@Override注解来显式指定

2.4 重写和重载的区别

方法重载是一个类的多态性表现,而方法重写式子类与父类的一种多态性表现

2.5 向上转型和向下转型

向上转型:实际就是创建一个子类对象,将其当作父类对象来使用

语法格式:父类类型 对象名=new 子类对象( )

Pet pet=new Dog("汪汪","犬科动物")

Pet是父类类型,但是可以引用一个子类对象,因为是从小范围到大范围的转换。

 使用场景:

1. 直接赋值

2. 方法传参

3. 方法返回

public class TestPet {
    //2.方法传参:形参为父类类型,可以接收子类对象
    public static void eat(Pet pet){
        pet.eat();
    }
    //3.作为返回值:返回任意子类对象
    public static Pet buyPet(String species){
        if("犬科动物".equals(species)){
            return new Dog("汪汪","犬科动物");
        }else if("猫科动物".equals(species)){
            return new Cat("咪咪","猫科动物");
        }else {
            return null;
        }
    }
    public static void main(String[] args) {
        //1.直接赋值:子类对象赋值给父类对象
        Pet cat=new Cat("咪咪","猫科动物");
        Pet dog=new Dog("旺旺","犬科动物");

        eat(cat);
        eat(dog);

        Pet pet=buyPet("犬科动物");
        pet.eat();

    }
}

向上转型的优点:让代码实现更加灵活

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

将一个子类对象经过向上转型后当成父类方法使用,再也无法调用子类特有的方法,但有时候可能需要子类特有的方法,此时我们引入了向下转型。

向下转型:将父类引用还原成子类对象。

向下转型存在不安全的特点,例如下述代码:

public class Pet{
    String name;
    String species;

    public Pet(String name, String species) {
        this.name = name;
        this.species = species;
    }
    public void eat(){
        System.out.println(name+"在进食");
    }

}
public class Dog extends Pet{
    public Dog(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃狗粮");
    }
    public void bark(){
        System.out.println("汪汪汪!");
    }
}
public class Cat extends Pet{
    public Cat(String name, String species) {
        super(name, species);
    }

    @Override
    public void eat() {
        System.out.println(name+"吃冻干");
    }
    public void mew(){
        System.out.println("喵喵喵!");
    }
}
public class TestPet {

    public static void eat(Pet pet){
        pet.eat();
    }

    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        //向上转型
        Pet pet=cat;
        pet.eat();
        pet=dog;
        pet.eat();
        //此时pet指向的是dog,强制还原为cat,无法正常还原,抛出ClassCastException
        cat= (Cat) pet;
        cat.mew();

        dog=(Dog) pet;
        dog.bark();

    }
}

 向下转型是不安全的,万一转型失败,运行时就会抛出异常。Java中为了提高向下转型的安全性,引入了instanceof,如果该表达式为true,则可以安全转型。

public class TestPet {

    public static void eat(Pet pet){
        pet.eat();
    }

    public static void main(String[] args) {
        Cat cat=new Cat("咪咪","猫科动物");
        Dog dog=new Dog("旺旺","犬科动物");
        //向上转型
        Pet pet=cat;
        pet.eat();
        pet=dog;
        pet.eat();
        
        if(pet instanceof Cat){
            cat= (Cat) pet;
            cat.mew();
        }

        if(pet instanceof Dog){
            dog=(Dog) pet;
            dog.bark();
        }
    }
}

2.6 多态的优缺点

多态的好处

1. 能够降低代码的圈复杂度,避免使用大量的if-else语句

圈复杂度是一种描述代码复杂程度的方式,一段代码平铺直叙,那么比较简单理解,如果有很多分支条件或者循环语句,就认为理解起来复杂。

2. 可拓展能力强

如果要新增一种行为,使用多态的方式代码改动的成本就比较低

多态的缺点:

1. 属性没有多态性

当父类和子类都有同名的属性时,通过弗雷德引用,只能引用父类自己的成员属性

2.构造方法没有多态性

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2024年11月架构设计师综合知识真题回顾,附参考答案、解析及所涉知识点(一)

软考高级系统架构设计师考试包含三个科目:信息系统综合知识、系统架构设计案例分析和系统架构设计论文。考试形式为机考。本文主要回顾2024年下半年(2024-11-10)系统架构设计师考试上午综合知识科目的选择题,同时附带参考答案、解析和所涉知识点。 由于机…

【STM32-学习笔记-8-】I2C通信

文章目录 I2C通信Ⅰ、硬件电路Ⅱ、IIC时序基本单元① 起始条件② 终止条件③ 发送一个字节④ 接收一个字节⑤ 发送应答⑥ 接收应答 Ⅲ、IIC时序① 指定地址写② 当前地址读③ 指定地址读 Ⅳ、MPU6050---6轴姿态传感器(软件I2C)1、模块内部电路2、寄存器地…

Angular-生命周期及钩子函数

什么是生命周期 Angular 创建和渲染组件及其子组件,当它们绑定的属性发生变化时检查它们,并在从 DOM 中移除它之前销毁它们。生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。当 Angular 使用构造函数新建一个组件或…

【计算机网络】深入浅出计算机网络

第一章 计算机网络在信息时代的作用 计算机网络已由一种通信基础设施发展成一种重要的信息服务基础设施 CNNIC 中国互联网网络信息中心 因特网概述 网络、互联网和因特网 网络(Network)由若干结点(Node)和连接这些结点的链路…

Golang——rune和byte

本文详细介绍Golang中的两种字符类型rune和byte,介绍他们的区别,编码方式和简单的使用。 文章目录 byte 类型rune 类型UTF-8 与 Unicode 的关系byte和rune的主要区别Go的默认编码方式遍历方式遍历 byte遍历 rune补充 字符还原从 byte 序列还原字符串从 r…

基于当前最前沿的前端(Vue3 + Vite + Antdv)和后台(Spring boot)实现的低代码开发平台

项目是一个基于当前最前沿的前端技术栈(Vue3 Vite Ant Design Vue,简称Antdv)和后台技术栈(Spring Boot)实现的低代码开发平台。以下是对该项目的详细介绍: 一、项目概述 项目名称:lowcode-s…

java springboot3.x jwt+spring security6.x实现用户登录认证

springboot3.x jwtspring security6.x实现用户登录认证 什么是JWT JWT(JSON Web Token)是一种开放标准(RFC 7519),它用于在网络应用环境中传递声明。通常,JWT用于身份验证和信息交换。JWT的一个典型用法是…

代码随想录刷题day07|(数组篇)58.区间和

目录 一、数组理论基础 二、前缀和 三、相关算法题目 四、总结 五、待解决问题 一、数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合。 代码随想录 (programmercarl.com) 特点: 1.下标从0开始,内存中地址空间是连续的 2.查询快&…

专用小软件,完全免费,非常丝滑

今天给大家介绍一个专门将PDF数电发票合并打印的软件,这个软件可以批量操作,完全免费没有任何的广告。 电子发票专用批量打印工具 免费批量使用 软件无需安装,解压之后双击这个图标就能直接使用了。 点击右上角的加号,选中需要打…

安装虚拟机VMware遇到的问题

问题1:进入如下界面,不知道如何操作 解决办法 键盘⬇️,选择“Reset the system”回车 问题2:系统存放位置我给放在了VMware安装目录,具体D:\software\VMware\Windows安装不行 解决办法:D:\software\virt…

Matlab 具有周期性分布的死角孔的饱和空气多孔材料的声学特性

本文对直主孔含侧空腔(死角)的饱和空气多孔介质中的声传播进行了理论和数值研究。侧腔位于沿每个主孔周期性间隔的“节点”上。研究了侧向空腔分布中周期性的影响,并单独考虑了紧间隔死角的低频极限。结果表明,吸附系数和透射损失…

Vue如何构建项目

目录 1.安装Node.js 2.换源(建议) 3.选择一个目录 4.创建一个vue项目 5.验证是否成功 1.安装Node.js 安装18.3或更⾼版本的 Nodejs 点击下载->Node.Js中文网 node -v npm -v 安装好后在windows的cmd窗口下运行 如果能运行出结果就说明安装好了。 2.换源(建议) //…

网络层协议-----IP协议

目录 1.认识IP地址 2.IP地址的分类 3.子网划分 4.公网IP和私网IP 5.IP协议 6.如何解决IP地址不够用 1.认识IP地址 IP 地址(Internet Protocol Address)是指互联网协议地址。 它是分配给连接到互联网的设备(如计算机、服务器、智能手机…

MacOS 下 Memory Analyzer 启动报错

👨🏻‍💻 热爱摄影的程序员 👨🏻‍🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻‍🏫 一位高冷无情的全栈工程师 欢迎分享 / 收藏 / 赞 / 在看…

sql模糊关联匹配

需求目标: 建立临时表 drop table grafana_bi.zbj_gift_2024;USE grafana_bi; CREATE TABLE zbj_gift_2024 (id INT AUTO_INCREMENT PRIMARY KEY,userName VARCHAR(255),giftName VARCHAR(255),giftNum INT,points INT,teacher VARCHAR(255),sendDate DATETIME,…

automake error: version mismatch

automake error: version mismatch REF:automake 编译提示版本报错 解决高版本不兼容低版本

C++----STL(string)

引言:STL简介 什么是STL STL(standard template libaray-标准模板库): 是 C标准库的重要组成部分(注意:STL只是C标准库里的一部分,cin和cout也是属于C标准库的),不仅是一个可复用的组件库&…

如何选择视频文件

文章目录 1. 概念介绍2. 方法与细节2.1 实现方法2.2 具体细节 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何选择多个图片文件"相关的内容,本章回中将介绍如何选择视频文件.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在前…

C++中的STL

STL(标准模板库)在广义上分为:容器,算法,迭代器 容器和算法之间通过迭代器进行无缝衔接 STL大体上分为六大组件:分别为容器,算法,迭代器,仿函数,适配器,空间…

Windows下安装和配置Go开发环境

文章目录 1. 介绍了SDK2. 下载 SDK工具包3. windows 下配置 Golang 环境变量 1. 介绍了SDK SDK 的全称(Software Development Kit 软件开发工具包)SDK是提供给开发人员使用的,其中包含了对应开发语言的工具包 2. 下载 SDK工具包 Go语言的官网为:https…