java面向对象进阶篇--《多态》

目录

一、前言

二、认识多态

方法重写(Override):

方法重载(Overload):

示例:

Person类(父类)

 Administrator(子类)

Student(子类)

Teacher(子类)

Text(测试类)

运行结果

示例解释

类的定义:

对象的创建和初始化:

方法调用:

多态的体现:

三、多态中调用成员的特点

动态绑定:

方法的重写(Override):

成员变量的访问:

静态方法和私有方法:

向上转型:

运行时类型识别(Instanceof):

示例:

类的结构:

对象的创建:

成员变量访问:

方法的调用:

总结:

四、多态的优势和弊端

优势:

灵活性和扩展性:

简化代码:

可替换性:

接口和抽象类的应用:

代码可读性和可理解性:

弊端:

运行时性能开销:

隐藏对象的实际类型:

可能引发运行时异常:

复杂性增加:

解决方法:

完整代码:

五、多态的综合练习

案例:饲养员喂动物

结果展示:

Animal类

Cat类

Dog类

Person类


一、前言

继续我们面向对象篇的学习,今天学习的是继承,这部分特别容易迷,多态是重点也是难点部分。概念了解一下即可,关键的会使用它。如果想要快速了解多态的用法,就直接看第五章。第五章是一个综合案例的全套源代码。

如果看着有些困难,不妨去看一下博主的另一篇文章。

 java继承icon-default.png?t=N7T8http://t.csdnimg.cn/2ZyyD

二、认识多态

多态(Polymorphism)是面向对象编程中一个重要的概念,它允许在不同类的对象上执行相同的操作,但具体执行的操作可能会有所不同。在Java中,多态性通过方法重写(Override)和方法重载(Overload)实现。

方法重写(Override)

  • 方法重写指子类重新定义或实现其父类的方法,方法名、参数列表和返回类型必须与父类方法完全一致。
  • 当子类对象通过父类引用调用被重写的方法时,实际执行的是子类的方法,而不是父类的方法。
  • 这种机制允许不同的子类对象表现出各自的行为,而不需要修改调用这些方法的代码。

方法重载(Overload)

  • 方法重载指在同一个类中,可以定义多个方法名相同但参数列表不同(参数类型、个数或顺序)的方法。
  • 编译器根据方法调用时传入的参数类型来决定具体调用哪个方法。
  • 方法重载并不是多态的实现方式,但它提供了一种静态的多态,即在编译阶段就确定了调用的方法。

示例:

Person类(父类)

public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void show(){System.out.println(name+","+age);}
}

 Administrator(子类)

public class Administrator extends Person{@Overridepublic void show() {System.out.println("管理员的信息为:"+getName()+getAge());}
}

Student(子类)

public class Student extends Person{@Overridepublic void show() {System.out.println("学生的信息为:"+getName()+getAge());}
}

Teacher(子类)

public class Teacher extends Person{@Overridepublic void show() {System.out.println("老师的信息为:"+getName()+getAge());}
}

Text(测试类)

public class Text {public static void main(String[] args) {Student s=new Student();s.setName("王同学");s.setAge(18);Teacher t=new Teacher();t.setName("王老师");t.setAge(30);Administrator a=new Administrator();a.setName("王管理员");a.setAge(40);register(s);register(t);register(a);}public static void register(Person p){p.show();}
}

运行结果

示例解释

类的定义

  • Text 类是程序的入口,其中包含了 main 方法。
  • StudentTeacherAdministrator 类都是 Person 类的子类,它们分别表示学生、老师和管理员,都继承自 Person 类。

对象的创建和初始化

  • Student s = new Student(); 创建了一个 Student 类型的对象 s,并设置了其姓名和年龄。
  • Teacher t = new Teacher(); 创建了一个 Teacher 类型的对象 t,并设置了其姓名和年龄。
  • Administrator a = new Administrator(); 创建了一个 Administrator 类型的对象 a,并设置了其姓名和年龄。

方法调用

  • register(s);register(t);register(a); 分别调用了 register 方法,并传入不同类型的对象作为参数。
  • register 方法的参数类型为 Person,因此可以接受 StudentTeacherAdministrator 类型的对象,这展示了多态的应用。
  • 在 register 方法内部,调用了 Person 类的 show 方法。由于子类 StudentTeacherAdministrator 都重写了 Person 类的 show 方法,因此实际上调用的是各自子类的 show 方法。

多态的体现

  • 多态使得在 register 方法中可以使用 Person 类型的参数,而实际传入的可以是其任何子类的对象。在运行时,根据实际对象的类型确定调用哪个子类的方法,这样可以根据需要处理不同类型的对象,而无需改变方法的定义。

三、多态中调用成员的特点

在Java中,多态性主要通过方法的动态绑定(也称为运行时多态)来实现。这种特性使得在运行时根据对象的实际类型来确定调用的方法,而不是在编译时确定。

动态绑定

  • 当通过父类引用调用子类对象的方法时,实际执行的是子类重写(覆盖)的方法。例如,如果父类有一个方法,子类覆盖了这个方法,那么当通过父类类型的引用调用这个方法时,实际执行的是子类的版本。

方法的重写(Override)

  • 子类可以通过重写父类的方法来提供特定于子类的实现。当父类的方法在子类中被重写后,通过父类引用调用该方法时,会调用到子类的方法实现。

成员变量的访问

  • 多态情况下,成员变量不具备多态性。即使子类覆盖了父类的成员变量,通过父类引用访问的仍然是父类的成员变量。这是因为成员变量的访问在编译时就已经确定了,而不会等到运行时才决定。

静态方法和私有方法

  • 静态方法和私有方法不具备多态性。静态方法是在编译时就确定的,因此不会被动态绑定,而是根据引用类型来确定调用的方法。私有方法也类似,子类中的同名私有方法不会覆盖父类的私有方法。

向上转型

  • 将子类实例赋给父类引用,称为向上转型。通过向上转型,可以实现对不同子类对象的统一处理,提高代码的灵活性和可扩展性。

运行时类型识别(Instanceof)

  • 可以使用 instanceof 运算符来判断一个对象的实际类型,这在多态中尤为有用,可以根据需要进行类型检查和转型操作。

示例:

public class text1 {public static void main(String[] args) {Fu f=new adog();Fu f1=new bdog();//调用成员变量System.out.println(f.name);System.out.println(f1.name);//调用方法f.show();f1.show();}}
class Fu{String name="Fu";public void show(){System.out.println("Fu--show");}
}
class adog extends Fu{String name="adog";@Overridepublic void show(){System.out.println("adog--show");}
}
class bdog extends Fu{String name="bdog";@Overridepublic void show(){System.out.println("bdog--show");}
}
类的结构
  • text1 类是程序的入口,包含了 main 方法。在 main 方法中,创建了两个 Fu 类型的引用,分别指向 adog 和 bdog 对象。
对象的创建
  • Fu f = new adog(); 创建了一个 adog 对象,并用 Fu 类型的引用 f 指向它。这是向上转型的示例,父类引用指向子类对象。
  • Fu f1 = new bdog(); 创建了一个 bdog 对象,并用 Fu 类型的引用 f1 指向它。
成员变量访问
  • 在Java中,成员变量不具备多态性。无论引用是什么类型,成员变量的访问都是由引用的类型决定的,而不是对象的实际类型。
  • Fu 类中有一个 name 成员变量,初始化为 "Fu"
  • adog 类和 bdog 类分别有自己的 name 成员变量,但是它们并不会覆盖父类 Fu 的 name 成员变量,而是在各自的类中定义了新的 name 变量。
方法的调用
  • 在多态的情况下,调用的方法由对象的实际类型决定。
  • f.show(); 调用的是 adog 类中重写的 show 方法,输出 "adog--show"
  • f1.show(); 调用的是 bdog 类中重写的 show 方法,输出 "bdog--show"
总结
  • 在成员变量访问中,引用类型决定了访问的成员变量,而方法调用则是根据对象的实际类型决定的(多态)。
  • 成员变量在多态中表现为静态绑定,而方法在多态中表现为动态绑定(运行时绑定)。
  • 成员变量看父类自己的,成员方法看是new的哪个对象。

四、多态的优势和弊端

优势:

灵活性和扩展性

  • 多态允许使用父类的引用来引用子类的对象,这样可以统一处理不同子类对象,提高了代码的灵活性和可扩展性。通过添加新的子类,而不需要修改现有的代码,可以轻松地扩展程序的功能。

简化代码

  • 多态可以使代码更加简洁,通过统一的接口来操作不同对象,减少了重复的代码,提高了代码的可读性和维护性。

可替换性

  • 可以随时替换具体的子类对象,而无需修改调用这些对象的代码。这种可替换性使得在运行时动态地改变程序的行为成为可能。

接口和抽象类的应用

  • 多态性使得接口和抽象类能够更好地发挥作用。通过接口和抽象类定义统一的规范,具体的子类可以按照自己的方式实现这些规范,从而提高了代码的可复用性和可维护性。

代码可读性和可理解性

  • 使用多态性可以使代码更加清晰和易于理解。通过使用父类类型的引用来操作对象,可以更专注于对象的行为和功能,而不必关注对象的具体类型。

弊端:

运行时性能开销

  • 在运行时,系统需要动态地确定对象的类型,然后调用相应的方法。这种动态绑定的过程可能会导致一些性能开销,尤其是在需要频繁调用的地方。

隐藏对象的实际类型

  • 多态性有时会隐藏对象的实际类型,这可能导致代码阅读和调试时的困惑。特别是当对象的具体类型在运行时才能确定时,理解代码的行为可能会更具挑战性。

可能引发运行时异常

  • 如果没有正确处理多态的边界条件和对象状态,可能会导致运行时异常,如空指针异常或类型转换异常。这需要在设计和实现中格外注意。

复杂性增加

  • 如果过度使用多态,可能会导致代码结构变得复杂,不易于理解和维护。因此,需要在设计中平衡使用多态性和明确的类型设计。

以上述代码为例,在子类中添加了一个特有的方法,因为父类中不存在,所以无法调用。 

解决方法:

完整代码:

//解决方法,将f强转为adogif(f instanceof adog a){a.adogshow();}else if(f instanceof bdog b){b.bdogshow();}else{System.out.println("没有这个类型,无法转换");}

instanceof关键字 

public void bdogshow(){System.out.println("bdog--bdogshow");}

为了代码的可读性,又在bdog类中添加了bdogshow方法。

注:不能转换成其他类型,容易报错。

五、多态的综合练习

写多态综合练习的时候,要将每一个类进行单独打包,Text测试类中不要有类的定义。

案例:饲养员喂动物

结果展示:

Animal类

package com.von.day11.text7;public class Animal {private int age;private String color;public Animal() {}public Animal(int age, String color) {this.age = age;this.color = color;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}//共有方法public void eat(String something){System.out.println("动物吃"+something);}
}

Cat类

package com.von.day11.text7;public class Cat extends Animal{public Cat() {}public Cat(int age, String color) {super(age, color);}@Overridepublic void eat(String something) {System.out.println(getAge()+"岁的"+getColor()+"颜色的猫吃"+something);}public void catchMouse() {System.out.println("猫抓老鼠");}
}

Dog类

package com.von.day11.text7;public class Dog extends Animal{public Dog() {}public Dog(int age, String color) {super(age, color);}@Overridepublic void eat(String something) {System.out.println(getAge()+"岁的"+getColor()+"颜色的狗抱住"+something+"猛吃");}public void lookHome(){System.out.println("狗看家");}
}

Person类

package com.von.day11.text7;public class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}//饲养狗public void keepPet(Dog dog, String something){System.out.println("年龄为" + this.age + "岁的" + this.name + "养了一只" + dog.getColor() + "颜色的" + dog.getAge() + "岁的狗");dog.eat(something);}//饲养猫public void keepPet(Cat cat, String something){System.out.println("年龄为" + this.age + "岁的" + this.name + "养了一只" + cat.getColor() + "颜色的" + cat.getAge() + "岁的猫");cat.eat(something);}
}

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

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

相关文章

docker搭建ES 8.14 集群

参考:【docker搭建es8集群kibana】_docker 安装生产级 es 8.14 集群-CSDN博客 1、之前已搭建一台单机版的dockerES集群 参见 Elasticsearch docker 安装_docker 安装es8.14.3-CSDN博客 2、现在需要重新搭建为docker ES集群 准备新搭建3个点 一、准备工作 提前开…

构建网络安全之盾:应对“微软蓝屏”教训的全面策略

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

深度学习模型Transformer结构

Transformer结构是一种基于自注意力(Self-Attention)机制的深度学习模型,最初由Vaswani等人在2017年的论文《Attention Is All You Need》中提出,用于解决自然语言处理(NLP)领域的任务,如机器翻…

MySQL --- 库的操作

一、创建数据库 create database [ if not exists ] 数据库名; // []中的为可选项 在创建库时,也可以指定数据库采用的字符集(character set)和数据库字符集的校验规则(collate) (当我们创建数据库没有指定字符集和校验规则时,系统使用默认字符集&#x…

【复习】软件工程

软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。 典型表现: 开发成本和进度的估计常常很不准确 用户对已完成的软件系统不满意,闭门造车 软件质量(quality)不可靠 软件常常是不可维护的 软件产品供不应…

css技巧混合模式

看上面这个神奇的效果,文字在黑色背景里面显示为白色,而在白色的背景里面显示为黑色,这就是文字智能适配背景。 看到这样的需求,大多数人第一时间想到的是,文字元素有两个,是完全重叠的两层,一…

Facebook在内容创作中的新策略与机会

随着社交媒体的不断发展,内容创作已经成为了平台吸引和留住用户的核心竞争力。Facebook作为全球最大的社交平台之一,不断调整和优化其内容创作策略,以适应用户需求的变化和技术的进步。本文将深入探讨Facebook在内容创作中的新策略与机会&…

考研复习7月进度严重滞后?

宇哥说:来不及了! 因为基础30讲和强化36讲,加起来已经快300小时了。 所以,必须换个思路: 不看课行吗? 大多数人7月的情况是这样的: 1. 听完线代,高数知识点忘得差不多了&#xf…

JMeter接口测试-3.断言及参数化测试

1. 断言 JMeter官方断言(Assertion)的定义 用于检查测试中得到的响应数据是否符合预期,用于保证测试过程中的数据交互与预期一致 断言的目的: 一个取样器可以添加多个不同形式的断言,根据你的检查需求来添加相应的…

自动驾驶系列—智能巡航辅助功能中的路口通行功能介绍

自动驾驶系列—智能巡航辅助功能中的车道中央保持功能介绍 自动驾驶系列—智能巡航辅助功能中的车道变换功能介绍 自动驾驶系列—智能巡航辅助功能中的横向避让功能介绍 自动驾驶系列—智能巡航辅助功能中的路口通行功能介绍 文章目录 2. 功能定义3. 功能原理4. 传感器架构5. 实…

Java语言程序设计基础篇_编程练习题**15.18(使用鼠标来移动一个矩形)

**15.18(使用鼠标来移动一个矩形) 请编写一个程序显示一个矩形。可以使用鼠标单击矩形内部并且拖动(即按住鼠标移动)矩形到鼠标的位置。鼠标点成为矩形的中央习题思路: 新建一个面板Pane(),新建一个Rectangle() 为Rectangle注册…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第三十九章 Linux MISC驱动

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

web每日一练

每日一题 每天一题罢了。。 ctfshow内部赛签到 扫到备份文件 login.php <?php function check($arr){ if(preg_match("/load|and|or|\||\&|select|union|\|| |\\\|,|sleep|ascii/i",$arr)){echo "<script>alert(bad hacker!)</script>&q…

微服务和VUE入门教程(16): zuul 熔断

1. 前言 在开发工程中&#xff0c;我们发现当一个微服务挂掉之后&#xff0c;如果我们访问此微服务的接口&#xff0c;zuul也会挂掉。因为zuul负责分配请求&#xff0c;当目标微服务挂掉之后&#xff0c;zuul便找不到目标微服务&#xff0c;因为我们需要设置一个熔断&#xff0…

电机调速控制模块说明文档

电机调速控制模块说明文档 图1-1总览图片 概述本电机控制模块是用于精确控制直流无刷电机运行、以及转速的关键组件&#xff0c;它能够实现对电机的启动、停止、调速、转向等操作&#xff0c;并提供多种保护功能&#xff0c;以确保电机的安全稳定运行。 驱动方式&#xff1a;…

如何学习Python:糙快猛的大数据之路(学习地图)

在这个AI和大数据主宰的时代,Python无疑是最炙手可热的编程语言之一。无论你是想转行还是提升技能,学习Python都是一个明智之选。但是,该如何开始呢?今天,让我们聊聊"糙快猛"的Python学习之道。 什么是"糙快猛"学习法? "糙快猛"学习法,顾名思…

OpenGL笔记十四之GLM数学库的配置与使用

OpenGL笔记十四之GLM数学库的配置与使用 —— 2024-07-20 中午 bilibili赵新政老师的教程看后笔记 code review! 文章目录 OpenGL笔记十四之GLM数学库的配置与使用1.旋转变换运行效果2.平移变换运行效果3.缩放变换运行效果4.复合变换&#xff1a;先旋转 再平移运行效果5.复合…

OpenTeleVision复现及机器人迁移

相关信息 标题 Open-TeleVision: Teleoperation with Immersive Active Visual Feedback作者 Xuxin Cheng1 Jialong Li1 Shiqi Yang1 Ge Yang2 Xiaolong Wang1 UC San Diego1 MIT2主页 https://robot-tv.github.io/链接 https://robot-tv.github.io/resources/television.pdf代…

八股文之java基础

jdk9中对字符串进行了一个什么优化&#xff1f; jdk9之前 字符串的拼接通常都是使用进行拼接 但是的实现我们是基于stringbuilder进行的 这个过程通常比较低效 包含了创建stringbuilder对象 通过append方法去将stringbuilder对象进行拼接 最后使用tostring方法去转换成最终的…

独立开发者系列(31)——fastadmin项目的二次开发

在前面构建项目的fastadmin入门 里面&#xff0c;我们已经能快速搭建该体系和根据数据表建立最简单的CURD项目。类似练手的图书管理系统&#xff0c;内部项目修改管理&#xff0c;也对系统进行了简单的部署。这梳理拿到真正项目的开发流程。 默认的开发目录和代码程序运行的是p…