4.4 多态

思维导图:

 4.4 多态

在深入研究对象的世界后,我们已经学到了封装和继承。接下来,我们要讨论的是面向对象编程的另一个核心概念:多态。

4.4.1 多态概述

多态是面向对象的三大特性之一,它允许我们以统一的方式处理不同类的对象。简单来说,多态允许一个接口或父类引用代表其任何派生类的对象。这意味着,我们可以设计一个方法,它的输入参数是父类类型,但当我们传递该方法的子类对象时,它会根据对象的实际类型执行相应的操作。

一个经典的例子是动物和它们的叫声。考虑一个“动物”抽象类和几个从动物类派生出来的子类,如“猫”和“狗”。虽然每种动物的叫声都是不同的,但我们可以定义一个方法,让它接受一个动物对象并让动物叫。当我们传递一个猫对象时,它会“喵喵叫”;当我们传递一个狗对象时,它会“汪汪叫”。

在Java中,多态主要体现在以下两个方面:

  1. 方法的重载:同一个方法名但参数类型或参数数量不同。
  2. 对象的多态(方法的重写):子类覆盖父类的方法。

4.4.2 多态示例

考虑以下的Java代码示例:

// 定义抽象类Animal
abstract class Animal {
    abstract void shout();
}

// 定义Cat类,继承自Animal
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵……");
    }
}

// 定义Dog类,继承自Animal
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("汪汪……");
    }
}

// 定义测试类
public class Example14 {
    public static void main(String[] args) {
        Animal an1 = new Cat();  // Cat对象向上转型为Animal
        Animal an2 = new Dog();  // Dog对象向上转型为Animal
        
        an1.shout();  // 输出“喵喵……”
        an2.shout();  // 输出“汪汪……”
    }
}

此代码展示了如何使用抽象类和继承来实现多态。当我们运行这个程序时,输出结果为:“喵喵……汪汪……”。

这是因为,尽管an1an2都是被声明为Animal类型的,但它们实际引用的对象是CatDog,因此当我们调用shout()方法时,它们分别执行了Cat类和Dog类中的实现。

这就是多态的魔力,允许我们编写更加通用、可扩展和可维护的代码。

4.4.2 对象类型的转换笔记


1. 对象类型转换概述

  • 向上转型: 子类对象 → 父类对象。
  • 向下转型: 父类对象 → 子类对象。

2. 对象向上转型

  • 当一个子类对象被当作父类对象使用时,就发生了向上转型。
  • 向上转型是自动完成的。

优点: - 增加程序的灵活性。 - 有助于隐藏具体的实现代码,从而更好地使用抽象类编写程序。

例子:

class Animal {
    public void shout() {
        System.out.println("喵喵……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example15 {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Animal an = dog; // 向上转型
        an.shout(); // 输出 "汪汪……"
    }
}

注意: - 一个向上转型的对象无法调用子类中特有的方法。


3. 对象向下转型

  • 使用向下转型来重新获得子类特有的属性和方法。
  • 向下转型必须明确指定转型的数据类型,并用强制类型转换符进行标识。
  • 必须先进行向上转型才能进行向下转型,否则会出现异常。

例子:

class Animal {
    public void shout() {
        System.out.println("喵喵……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example16 {
    public static void main(String[] args) {
        Animal an = new Dog(); // 向上转型
        Dog dog = (Dog)an;    // 向下转型
        dog.shout(); // 输出 "汪汪……"
        dog.eat();   // 输出 "吃骨头……"
    }
}

注意: - 不能直接将父类实例强制转换为子类实例,这会导致错误。例如: java Dog dog = (Dog) new Animal(); // 编译错误


通过以上的解释和示例代码,我们可以明白Java中对象的向上转型和向下转型的原理及其用法。

4.4.3 instanceof关键字笔记


1. 简介

  • Java提供了instanceof关键字,用于判断一个对象是否是某个特定类或接口的实例。

语法格式:

对象 instanceof 类(或接口)
  • 如果“对象”是指定的类或接口的实例对象,则结果返回true,否则返回false

2. 示例

文件4-17 Example17.java:

class Animal {
    public void shout() {
        System.out.println("动物叫……");
    }
}

class Dog extends Animal {
    public void shout() {
        System.out.println("汪汪……");
    }
    public void eat() {
        System.out.println("吃骨头……");
    }
}

public class Example17 {
    public static void main(String[] args) {
        Animal a1 = new Dog(); // 向上转型
        System.out.println("Animal a1 = new Dog():" + (a1 instanceof Animal));
        System.out.println("Animal a1 = new Dog():" + (a1 instanceof Dog));

        Animal a2 = new Animal(); 
        System.out.println("Animal a2 = new Animal():" + (a2 instanceof Animal));
        System.out.println("Animal a2 = new Animal():" + (a2 instanceof Dog));
    }
}

输出:

Animal a1 = new Dog():true
Animal a1 = new Dog():true
Animal a2 = new Animal():true
Animal a2 = new Animal():false

3. 结论和解析

  • 当一个对象是一个类的实例或者是其子类的实例时,使用instanceof检查会返回true
  • 在上面的示例中,a1Dog类的实例,因此它既是Dog的实例又是Animal的实例。
  • a2仅仅是Animal的实例,不是Dog的实例,所以当我们检查它是否是Dog的实例时,返回false

使用instanceof关键字,我们可以在运行时判断对象的实际类型,从而做出相应的逻辑判断。这在多态的情境中尤其有用,可以让我们更加灵活地处理不同类型的对象。

4.4 多态总结


1. 重点:

  • 定义: 多态是面向对象编程的三大特性之一,允许将子类的对象当作父类的对象使用。
  • 实现: Java中的多态主要依赖于继承、接口和重写。
  • 向上转型: 当子类对象被当作父类对象使用时,会发生自动的向上转型。例如:Animal a = new Dog(); 这里,Dog对象自动转型为Animal。
  • 向下转型: 可以使用强制类型转换将父类对象转为子类对象,但在转型之前,该对象确实应该是那个特定子类的实例。例如:Dog d = (Dog) a; 这里,a必须实际上是Dog的一个实例。
  • instanceof 关键字: 可以检查一个对象是否是某个特定类或接口的实例。

2. 难点:

  • 理解: 对于初学者,理解不同对象之间的动态绑定可能是个挑战。
  • 向下转型的风险: 若试图对不正确的类型进行向下转型,会引发运行时异常。例如,若a是Cat的实例,那么(Dog) a将抛出异常。
  • 方法调用: 当使用多态时,始终会调用实际对象的重写方法,而不是引用变量的类型的方法。这意味着,对于上面的例子,如果Dog类重写了shout方法,那么a.shout()将调用Dog类的shout方法,而不是Animal类的。

3. 易错点:

  • 误解向下转型: 很多初学者可能认为,任何父类引用都可以被向下转型为任何子类,这是错误的。例如,Animal a = new Animal(); Dog d = (Dog) a; 这将导致运行时异常。
  • 丢失功能: 在向上转型后,只能调用在父类中定义的方法和属性,即使子类有更多的功能。例如,如果Dog类有一个特有的fetch方法,那么你不能使用Animal引用a来调用a.fetch()
  • 混淆方法覆盖与重载: 多态涉及到方法覆盖(子类提供父类方法的特定实现),而不是方法重载(同一个类中的方法有不同的参数)。

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

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

相关文章

518抽奖软件,可从Excel~Word~Pdf~网页导入名单

518抽奖软件简介 518抽奖软件,518我要发,超好用的年会抽奖软件,简约设计风格。 包含文字号码抽奖、照片抽奖两种模式,支持姓名抽奖、号码抽奖、数字抽奖、照片抽奖。(www.518cj.net) 从Excel、WPS表格导入 整列: 用鼠…

Vue路由(router)的安装和使用

Vue路由(router)的安装和使用 安装vue-router插件 第一步:在CMD窗口中,使用命令跳转到vue的安装路径下第二步:输入命令:npm i vue-router3 vue2 要安装 vue-router3 npm i vue-router3 vu3 要安装 vue-ro…

如何使用IP归属地查询API加强网络安全

目录 一、背景与意义 二、IP归属地查询API加强网络安全的方式 三、IP归属地API的使用教程 四、实际代码示例 五、结合其他安全技术加强网络安全 六、注意事项 总结 一、背景与意义 在数字化的今天,网络安全问题变得尤为重要。企业、组织乃至个人都面临着网络…

MacBook终端安装tree命令(保证好使)

1. 首先在终端安装brew 由于mac是没有原生支持tree命令的,所以我们在安装tree命令之前,先安装brew。 先输入下面命令,安装brew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)…

CRM系统如何帮助大客户销售

我们知道大客户都具备这样的特点:对企业价值高、成交难度大、成单周期长,因此这一部分客户需要销售团队投入更多的时间和精力。大客户销售如何利用好CRM系统更大程度地挖掘大客户价值?关键还在于维护好客户生命周期。 销售人员想要拿下大客户…

综合实验案例配置

目录 核心交换机与出口路由器的连接 网络出口的配置 策略路由的配置 1.教学楼的流量走电信出口,宿舍楼流量走联通出口(基于源) 2.访问带内心的服务器走电信出口,访问联通服务器走联通出口 案例图如下: acsw的配置…

RecyclerView在点击事件的处理上也优于ListView

主要是细节的支持,ListView直接提供setOnItemClickListener,而RecyclerView没有,是因为RV考虑的更细节,比如我要点击条目上的某个图标生效,使用ListView会很难实现,但是RV实现会很容易,直接在适配器中由Vie…

【进阶C语言】数组笔试题解析

本节内容以刷题为主,大致目录: 1.一维数组 2.字符数组 3.二维数组 学完后,你将对数组有了更全面的认识 在刷关于数组的题目前,我们先认识一下数组名: 数组名的意义:表示数组首元素的地址 但是有两个例外…

Kubernetes·陈述式声明式资源管理

目录 k8s陈述资源管理方法的说明 陈述式资源管理方法 声明式资源管理方法 GUI式资源管理方法 kubectl命令行工具 的说明 查看版本信息 查看资源对象简写 查看集群信息 配置kubectl自动补全 node节点查看日志 k8s基本信息查看 查看 master 节点状态 查看命名空间 …

【MySQL】MySQL的安装与配置环境变量(使其在控制台上使用)

作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《MySQL》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造&a…

sqlite3 关系型数据库语言 SQL 语言

SQL(Structured Query Language)语言是一种结构化查询语言,是一个通用的,功能强大的关系型数据库操作语言. 包含 6 个部分: 1.数据查询语言(DQL:Data Query Language) 从数据库的二维表格中查询数据,保留字 SELECT 是 DQL 中用的最多的语句 2.数据操作语言(DML) 最主要的关…

【Git企业开发】第四节.Git的分支管理策略和bug分支

文章目录 前言一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 1.2 企业分支管理策略二、bug分支三、删除临时分支四、总结总结 前言 一、Git的分支管理策略 1.1 Fast forward 模式和--no-ff 模式 通常合并分支时,如果可能,Git 会…

Mac docker+vscode

mac 使用docker vs code 通过vscode 可以使用docker容器的环境。 可以在容器安装gdb, 直接调试代码。 创建容易时候可以指定目录和容易目录可以共享文件。

空气质量查询API促使空气数据可视化

引言 在当今的现代化社会中,关注和改善空气质量已成为人们共同的关切。随着科技的不断发展,空气质量查询API为我们提供了一种前所未有的方式来实时监测、分析和改善我们所处的环境。这一工具不仅让我们更深入地了解空气质量,还鼓励了空气数据…

Java如何使用KEPserver 实现S71500 OPC通信

一.PLC和OPC 使用的PLC:西门子PLC S7-1500 使用的OPC server软件: KEPServer V6 二.连接测试 OPC是工业控制和生产自动化领域中使用的硬件和软件的接口标准,以便有效地在应用和过程控制设备之间读写数据。O代表OLE(对象链接和嵌入)&am…

Qt 使用Quazip解压缩、压缩文件

1.环境搭建 Quazip,是在zlib基础上进行了简单封装的开源库,适用于多种平台,利用它可以很方便将单个或多个文件打包为zip文件,且打包后的zip文件可以通过其它工具打开。 下载Quazip QuaZIP download | SourceForge.net 解压后&…

cnpm windows系统安装后查看版本cnpm -v报错Error: Cannot find module ‘node:util‘

1、报错截图 2、原因 在网上查了一些资料,有的说配置环境变量就可以,但经过配置后发现还是会报错。又查到说是由于cnpm和npm的版本不一致导致的,最后尝试成功解决!!! 2、解决办法 1、先卸载掉之前安装的c…

【扩散模型】理解扩散模型的微调(Fine-tuning)和引导(Guidance)

理解扩散模型的微调Fine-tuning和引导Guidance 1. 环境准备2. 加载预训练过的管线3. DDIM——更快的采样过程4. 微调5. 引导6. CLIP引导参考资料 微调(Fine-tuning)指的是在预先训练好的模型上进行进一步训练,以适应特定任务或领域的过程。这…

DSP 开发例程: 单镜像多核引导

目录 DSP 开发例程: 单镜像多核引导新建工程源码编辑multicore_boot.c config.hos.cmain.c测试 DSP 开发例程: 单镜像多核引导 此例程实现在 EVM6678L 开发板上将单镜像应用程序进行多核引导, 核0-核4 分别控制一个LED 闪烁, 并通过串口打印日志信息. 例程源码可从我的 gitee …

今日温馨早安问候语,祝大家平安健康早安吉祥

用清晨的阳光沐浴,给你舒展;用清新的空气洗漱,给你舒心;伴清莹的雨露散步,给你舒情;向美好的一天欢呼,给你舒怀,用快乐的词汇凝聚,给你祝福,祝你在绚丽的晨光中走好每一天。朋友,早安…