【Java面向对象】多态

news2024/9/20 18:43:57

文章目录

  • 1.动态绑定
  • 2.对象转换和 instanceof 操作符
  • 稍作总结
  • 3.Object 类的 equals 方法
  • 4.ArrayList 类
  • 5.继承体系中的权限问题
  • 6.final

1.动态绑定

多态意味着父类型的变量可以引用子类型的对象。
方法可以在沿着继承链的多个类中实现。JVM 决定运行时调用哪个方法。

一个变量必须被声明为某种类型。变量的这个类型称为它的声明类型 ( declared type)。这里,o 的声明类型是A。
变量的实际类型 ( actualtype) 是被变量引用的对象的实际类。这里,o 的实际类型是 B, 因为 o 引用使用 B创建的对象。o 调用哪个print() 方法由 o 的实际类型决定。这称为动态绑定 (dynamicbinding)。

即父类变量指向子类对象时,调用同名方法时,调用的是子类的,除非子类没有才会调用父类的。
方法可以在沿着继承链的多个类中实现。调用同名方法时,调用的是子类的,如果子类没有重写,就一直挨个挨个往"上辈"找。

public class DynamicBindingDemo {
	public static void main(String[] args) {
		m(new Graduatestudent() ) ;
		m(new Student() ) ;
		m(new Person() ) ;
		m(new Object() ) ;
	}
	public static void m(Object x) {
		System.out.println(x.toString() ) ;
	}
}
class Graduatestudent extends Student {
}
class Student extends Person {
	©Override
	public String toString() { 
		return "Student";
	}
}
class Person extends Object {
	©Override
	public String toString() {
		return "Person";
	}
}

/*Student
Student
Person
java.1ang.Object@130c19b*/

2.对象转换和 instanceof 操作符

一个对象的引用可以类型转换为对另 外一个对象的引用,这称为对象转换。

m(new Student());
// 等价于
Object o = new Student(); // 隐式转换 (implicit casting)
m(o);

总是可以将一个子类的实例转换为一个父类的变量,称为向上转换 ( upcasting), 因为子类的实例总是它的父类的实例。当把一个父类的实例转换为它的子类变量 (称为向下转换(downcasting)) 时,必须使用转换标记 “(子类名)”进行显式转换。

Student b = (Student)o;

如果一个对象不是 Student 的实例,它就不能转换成 Student 类型的变量。因此,一个好的做法是,在尝试转换之前确保该对象是另一个对象的实例。这可以利用操作符 instanceof 来实现。
instanceof看的是实际类型。

void f(Object obj){
	if(obj instanceof Student){
		obj.printId(); // 假设printId是Student类的一个对象函数。}
}

变量 obj被声明为object类,声明类型决定了在编译时匹配哪个方法。使用obj.printId()会引起一个编译错误,因为Object 类没有 printId()方法。所以,有必要将obj转换成Student类型,以告诉编译器obj也是 Student的一个实例。
为什么不在一开始就把 myObject 定义为 Circle 类型呢?为了能够进行通用程序设计,一个好的做法是把变量定义为父类型,这样,它就可以接收任何子类型的对象

public class Test{
	public static void main(Stringp[] args){
		Object obj1 = new Circle(1);
		Object obj2 = new Rectangle(1,1);

		display(obj1);
		display(obj2);
	}
	public static void display(Object obj){
		if(obj instanceof Circle)
			((Circle)obj).showradius();
		else if(obj instanceof Rectangle)
			((Rectangle)obj).showarea();
	}
}

对基本类型值进行转换不同于对对象引用进行转换。转换一个基本类型值返回一个新的值。转换一个对象引用不会创建一个新的对象。

// a和b是不同的东西
double a = 4.5; 
int b = (int)a; // 4

// o和a指向同一个对象
Object o = new A(); // 声明为Object,实际为A
A a = (A)o; // 声明为A,实际为A

稍作总结

本文第一点指的是子类重写父类方法的现象。
父类变量可以指向子类对象,而且用父类变量调用父类和子类同名的方法时,调用的会是子类中重写后的方法。
当父类被多个子类继承时,假设不同的子类对父类中的同一个函数进行不同版本的重写。那么之后当父类变量指向不同的子类对象时,调用这个同名函数,就可以根据不同的子类对象而调用不同的重写后的版本

本文第二点指的是子类相比父类有新的方法的现象。
用父类变量指向子类对象时,声明类型是父类,实际类型是子类。由于声明类型是父类,所以这个父类变量不能调用子类新定义的方法。
只能先通过instanceof关键词判断实际类型是哪个子类,然后通过类型转换转化为对应的子类,然后调用对应的方法

总而言之,能不能调用某个方法,取决于声明类型(比如第2点中,声明类型为父类的对象不能调用只在子类中存在的方法)。
具体调用哪个方法,取决于实际类型(1.父类和子类存在同名方法,父类变量指父类对象,用的自然是父类的。子类变量是子类对象,要的自然是子类的。父类变量指子类对象,用的是子类的。子类变量指不了父类对象2.父类有而子类无的对象,无论什么情况都是调用父类的)

能不能(编译器同不同意)调用某个方法,取决于声明类型
具体调用哪个方法,取决于实际类型

3.Object 类的 equals 方法

比较操作符 ==用来比较两个基本数据类型的值是否相等,或者判断两个对象是否具有相同的引用。
如果想让 equals 方法能够判断两个对象是否具有相同的内容,可以在定义这些对象的类时,重写equals 方法。

4.ArrayList 类

ArrayList即数组列表
ArrayList 对象可以用于存储一个对象列表。
可以创建一个数组存储对象,但是这个数组一旦创建,它的大小就固定了。Java 提供了 ArrayList 类,可以用来存储不限定个数的对象。

ArrayList 是一种泛型类,具有一个泛型类型E创建一个 ArrayList 时,可以指定一个具体的类型来替换E。

储在 ArrayList 中的元素必须是一种对象。不能使用诸如 int 的基本数据类型来代替一个泛型类型。然而,可以创建一个存储工Integer 对象的ArrayList
在这里插入图片描述

ArrayList<AConcreteType> list = new ArrayList<AConcreteType>();

ArrayList<AConcreteType> list = new ArrayList<>(); //类型推导 (type inference)

ArrayList 的大小是灵活的,所以无须提前给定它的大小。而当创建一个数组时,它的大小必须给定。可以使用 foreach 循环来遍历数组中的元素。数组列表ArrayList中的元素也可以使用 foreach 循环来进行遍历。

5.继承体系中的权限问题

修饰符 protected 和 public 都称为可见性修饰符( visibility )或可访问性修饰符(accessibility) 因为它们指定如何访问类和类的成员。
在这里插入图片描述
类可以以两种方式使用:一种是用于创建该类的实例;另一种是通过继承该类创建它的子类。如果不想从类的外部使用类的成员,就把成员声明成private如果想让该类的用户都能使用类的成员,就把成员声明成 public,如果想让该类的继承类使用数据和方法,而不想让该类的用户使用,则把成员声明成protected。

修饰符 private 和 protected 只能用于类的成员。public 修饰符和默认修饰符(也就是没有修饰符)既可以用于类的成员,也可以用于类。一个没有修饰符的类(即非公共类)是不能被其他包中的类访问的。

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
原文:https://blog.csdn.net/Liebers/article/details/82697949

另外还有重写的原则:

覆盖方法必须满足的十大约束
一:子类方法的名称、参数签名和返回类型必须与父类方法的名称、参数签名和返回类型一致
二:子类方法不能缩小父类方法的访问权限
三:子类方法不能抛出比父类方法更多的异常,子类方法抛出的异常必须和父类方法抛出的异常相同,或者子类方法抛出的异常类是父类方法抛出的异常类的子类
四:方法覆盖只存在于子类和父类(包括直接父类和间接父类)之间。在同一个类中方法只能被重载,不能被覆盖。
五:父类的静态方法不能被子类覆盖为非静态方法。
六:子类可以定义与父类的静态方法同名的静态方法,以便在子类中隐藏父类的静态方法。子类隐藏父类的静态方法和子类覆盖父类的实例方法,这两者的区别在于:运行时,Java虚拟机把静态方法和所属的类绑定,而把实例方法和所属的实例绑定。
七:父类的非静态方法不能被子类覆盖为静态方法。
八:父类的私有方法不能被子类覆盖。
九:父类的抽象方法可以被子类通过两种途径覆盖:一是子类实现父类的抽象方法;二是子类重新声明父类抽象方法。
十:父类的非抽象方法可以被覆盖为抽象方法。
原文链接:https://blog.csdn.net/pickpocket/article/details/83923446

最后说一下public修饰类。
如果一个类声明的时候使用了public class进行了声明,则类名称必须与文件名称完全一致。被public修饰的类可以被其他包访问。
如果一个类声明的时候使用了class进行了声明,则作为启动类的名称可以与文件名称不一致,但是执行的时候肯定执行的是生成后的名称。没有public修饰的类,该类就拥有了包访问权限,即该类只可以用于该包之中。

6.final

一个被 final 修饰的类和方法都不能被继承。被 final 修饰的数据域是一个常数。
final的用法:
1.修饰类:当用final修饰一个类时,表明这个类不能被继承。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
2.修饰方法:把方法锁定,以防任何继承类重写。
3.修饰变量:对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

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

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

相关文章

新手小白攻略:如何用AI工具搭建个人知识库

个人知识库是指个人通过积累和整理&#xff0c;将各种领域的知识、经验和技能进行分类、归纳和存储的系统化工具或平台。 随着信息技术的飞速发展和知识经济的兴起&#xff0c;个人知识库不仅成为个人学习、成长和创新的基石&#xff0c;也是适应快速变化社会、提升竞争力的关…

python--实验 11 模块

目录 知识点 模块基础 模块使用方式 自定义模块示例 模块的有条件执行 Python包结构 定义和导入包 常用第三方库及安装 实例代码 第三方库自动安装脚本 Python标准库介绍 PyInstaller 小结 实验 1.(基础题)制作文本进度条。 2.(基础题) 蒙特卡罗方法计算圆周率…

nginx全局块的user指令

文章目录 1、user指令1.1、进入nginx解压的目录1.2、./configure --help1.3、工作进程默认是nobody 2、user指令的使用步骤:2.1、设置一个用户信息"www"2.2、 创建一个用户2.3、./nginx -s reload2.4、创建/root/html/index.html页面&#xff0c;添加如下内容2.5、修…

住宅IP解析:动态住宅IP和静态住宅IP区别详解

在互联网连接的世界中&#xff0c;IP地址是我们识别和访问网络资源的关键。住宅IP地址&#xff0c;特别是动态住宅IP和静态住宅IP&#xff0c;是两种不同类型的IP分配方式&#xff0c;它们在使用和功能上存在显著差异。 1. IP地址的稳定性 动态住宅IP&#xff1a;这种IP地址是…

昇思25天学习打卡营第14天|munger85

基于MindNLPMusicGen生成自己的个性化音乐 这个所谓的个性化的音乐就是指你输入一段文字它会根据这个文字输出一段音乐这个音乐是贴近于那段文字的所以叫做文生成音乐&#xff0c; 如果网络正常的话就可以直接从下载这个模型。 那么音乐生成的有两种方式呢有两种方式&#xff…

layui 让table里的下拉框不被遮挡

记录&#xff1a;layui 让table里的下拉框不被遮挡 /* 这个是让table里的下拉框不被遮挡 */ .goods_table .layui-select-title,.goods_table .layui-select-title input{line-height: 28px;height: 28px; }.goods_table .layui-table-cell {overflow: visible !important; }.…

[C++初阶]list的模拟实现

一、对于list的源码的部分分析 1.分析构造函数 首先&#xff0c;我们一开始最先看到的就是这个结点的结构体&#xff0c;在这里我们可以注意到这是一个双向链表。有一个前驱指针&#xff0c;一个后继指针。然后在有一个存储数据的空间 其次它的迭代器是一个自定义类型&#x…

【Python游戏】编程开发贪吃蛇游戏(第一期)

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、贪吃蛇游戏开发简介2.1 贪吃蛇游戏规则2.2 贪吃蛇游戏开发步骤 三、贪吃蛇游戏开发实战四、总结…

13 个最受欢迎的技术写作工具

13 个最受欢迎的技术写作工具 在我的职业生涯中&#xff0c;我作为技术作家工作了大约 10 年&#xff0c;根据需要使用了各种文档工具。作为技术作家&#xff0c;主要工作职责是提供正确的内容。 使用正确的技术写作工具可以使技术作家的生活变得轻松。有多种工具可用于不同的…

【Vue】Vue3 安装 Tailwind CSS 入门

初始化 Vue 3 项目 npm install -g vue/cli vue create my-project安装 Tailwind CSS 进入你的项目目录&#xff0c;然后安装 Tailwind CSS 和其依赖项&#xff1a; npm install -D tailwindcss postcss autoprefixer配置 PostCSS Tailwind CSS 需要通过 PostCSS 进行处理。…

Linux发行版CentOS 8 利用Docker安装应用

目录 一、什么是Docker&#xff1f; 主要功能&#xff1a; 二、安装Docker 1.安装yum配置工具 2.配置docker的yum源 3.安装 4.测试 5.启动&#xff0c;关闭&#xff0c;开机自启动 三、卸载Docker 1.停止服务 2.卸载 3.删除文件 四、Docker配置镜像源 1.在etc下创建docker…

【大模型时代的PDF解析工具】

去年&#xff08;2023年&#xff09;是大模型爆发元年。但是大模型具有两个缺点&#xff1a;缺失私有领域知识和幻觉。缺失私有领域知识是指大模型训练时并没有企业私有数据/知识&#xff0c;所以无法正确回答相关问题。并且在这种情况下&#xff0c;大模型会一本正经地胡说八道…

JavaEE--JavaWeb服务器的安装配置(Tomcat服务器安装配置)

前言: 本文介绍了 Java Web 服务器 Tomcat 的安装配置&#xff0c;并详细说明了如何在 IntelliJ IDEA 中配置服务器&#xff0c;创建 JavaEE 项目&#xff0c;并发布文章。文章首先解释了前端程序如何访问后端程序以及 Web 服务器的概念&#xff0c;然后详细介绍了安装 Tomcat…

VirtualBox虚拟机与主机互传文件的方法

建立共享文件夹 1.点击设置&#xff0c;点击共享文件夹&#xff0c;添加共享文件夹路径&#xff0c;保存 2.启动虚拟机&#xff0c;点击设备&#xff0c;点击安装增强功能&#xff0c;界面会出现一个光碟图标&#xff0c;点击光碟图标 3.打开光碟图标&#xff0c;出现一个目…

Vue3渐变文字(GradientText)

效果如下图&#xff1a;在线预览 APIs GradientText 参数说明类型默认值必传gradient文字渐变色参数string | Gradientundefinedfalsesize文字大小&#xff0c;不指定单位时&#xff0c;默认单位 pxnumber | string14falsetype渐变文字的类型‘primary’ | ‘info’ | ‘succ…

【大模型】FAISS向量数据库记录:从基础搭建到实战操作

文章目录 文章简介Embedding模型BGE-M3 模型亮点 FAISS是什么FAISS实战安装faiss加载Embedding模型创建FAISS数据库搜索FAISS数据删除FAISS数据保存、加载FAISS索引 总结 本人数据分析领域的从业者&#xff0c;拥有专业背景和能力&#xff0c;可以为您的数据采集、数据挖掘和数…

Java语言程序设计基础篇_编程练习题**14.29(游戏:豆机)

第十四章第二十九题 **14.29 (游戏&#xff1a;豆机) 请写一个程序&#xff0c;显示编程练习题 7.21 中介绍的豆机&#xff0c;如图 14-52c 所示 代码展示 package chapter_14;import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.layou…

易保全参与起草的两项区块链全国团体标准正式发布

在数字化转型浪潮席卷全球的今天&#xff0c;区块链技术以其去中心化、透明性、不可篡改等独特优势&#xff0c;正逐步成为重塑各行各业信任机制与业务流程的关键力量。 近日&#xff0c;中国通信工业协会正式发布了《区块链服务 基于区块链的去中心化标识符技术要求》与《区块…

什么是反向代理?

这里写目录标题 一、什么是反向代理&#xff1f;二、反向代理的工作原理三、使用反向代理的好处四、反向代理的风险 在网络领域中&#xff0c;代理服务器是一种常见的技术&#xff0c;用于转发客户端和服务器之间的请求和响应。代理服务器又可以分为反向代理和正向代理两种类型…

QT实现图片开关控件-自定义控件

开关按钮大家应该很熟悉&#xff0c;在设置里面经常遇到&#xff0c;切换时候的滑动效果比较帅气。通常说的开关按钮&#xff0c;有两个状态&#xff1a;on、off。大部分的开关按钮控件&#xff0c;基本上有两大类&#xff0c;第一类是纯代码绘制&#xff0c;这种对代码的掌控度…