Java-抽象类和接口

devtools/2024/10/25 0:45:47/

一、抽象类

① 抽象类的概念

在上一篇文章中,我们学习了" 多态 ",它允许在相同方法的情况下处理不同的对象,即通过父类引用指向子类对象,并调用相同的方法,通过不同的子类调用该方法,进而产生不同的结果。抽象类也和" 多态 "有着很大的关联。

📌 抽象类的定义如果一个类中没有包含足够的信息来描述一个具体的对象,那么这样的类就是抽象类。

📕 抽象类不能被实例化,只能作为其他类的父类或供其他类继承。

📕 抽象类可以包含抽象方法和普通方法。

📚 那么抽象类应该如何使用呢?抽象方法又是什么呢:

通过这个图我们可以看到,Animal的sound()方法被Dog,Cat,Duck继承后,调用方法后结果都各不相同,这也是" 多态 "的体现。但我们注意:

在抽象类的使用下,Animal的sound()方法并不像上篇文章中所学,是有具体实现的,而是一个没有方法体的方法,正因为它没有方法体,所以它才称之为"抽象";而在这张图片中"Animal"中的"sound"方法就是一个抽象方法而"Animal"就是一个抽象类~

所以我们刚刚说抽象类也和" 多态 "有着很大的关联。

这是因为多态可以通过抽象类实现抽象类可以包含抽象方法这些方法没有具体的实现,只有方法的声明子类继承抽象类时必须!!!实现抽象方法,这样就可以通过父类引用调用子类的实现。这样一来,同一个方法名可以根据具体的子类对象而有不同的表现形式,实现了多态。

📚注意:(不用抽象类时是"重写",本质是覆盖;而用抽象类时是"实现",两者本质不同)

② 抽象类的实现

当我们想要创建一个抽象类时,这个类就必须要被"abstract"修饰,如此才能被称作抽象类。

📚 那么让我们试着实现一下上面图片中的例子

📕 抽象类"Animal"

📕 继承"Animal"的子类们

可以看到,所有继承了抽象类"Animal"的子类们都实现了sound()方法,这是因为:

📚 继承了抽象类的子类必须实现其中的抽象方法,因为(抽象类无法实例化),而继承了抽象类的子类如果不实现抽象方法,便也算是(抽象类),为了防止它被实例化,所以会报错:

可以看到,这时就报错了~

正常运行

③ 抽象类的特征

📚 抽象类的特征有如下几点

📕 抽象类不能直接实例化对象:

📕 抽象方法不能是 private 的:

📕 抽象方法不能被 final 和 static 修饰,因为需要被子类实现:

📕 继承抽象类的子类必须重写父类中的抽象方法,否则子类也要是抽象类:

如果子类不重写父类抽象方法:

如果抽象类子类不重写父类抽象方法:

📕 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类

📕 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

二、接口

① 接口的概念

接口,这个词大家听起来不陌生吧~接口在我们印象中可能就是:USB接口呀,充电插口呀~之类的。没错,它们都可以叫做接口,而且它们都有一种统一的性质

📕 智能产品可以通过USB接口,来开启信号的权限,就相当于被赋予某种功能(信号)

📕 家用电器可以通过电源插孔,开开启充电的权限,就相当于被赋予某种功能(充电)

由此可以得出结论

📚 接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。 在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

② 接口的实现

接口的定义格式与定义类的格式基本相同

将class关键字换成 interface 关键字,就定义了一个接口。

📚 代码格式:

java">public interface 接口名称{// 抽象方法
public abstract void method1();   // public abstract 是固定搭配,可以不写
public void method2();abstract void method3();void method4();
}

需要注意的是,接口里面的方法也都是待实现的抽象方法

接口中可以声明方法,但是不能包含方法的具体实现。接口中的方法默认为public abstract,可以省略这些修饰符。接口也可以包含常量的声明,这些常量默认为public static final,同样可以省略这些修饰符。

📚 代码实例

📌 "接口"的相关知识还是比较模糊的,既然学到了,就让我们做一个小练习来试一试:

📚 实现笔记本电脑使用USB鼠标、USB键盘的例子

1. USB接口:包含打开设备、关闭设备功能

2. 笔记本类:包含开机功能、关机功能、使用USB设备功能

3. 鼠标类:实现USB接口,并具备点击功能

4. 键盘类:实现USB接口,并具备输入功能

其实大部分功能都是可以通过之前所学到的基础知识"if","else","switch"等选择语句去实现的,但是使用"接口",会使代码更加具有规范性和可读性,可修改性,是我们学习的必经之路,并且相当重要~

让我们先来仔细地思考一下,这些东西应该如何去一一实现

📕 理清这几种类与接口的关系

📕 然后按照理清后的关系图,依次进行接口和类的创建:

📌 USB 接口

(由于整理得到:USB接口带有[打开设备][关闭设备]两种功能,所以我们写上~)

(我写上public abstrac 不是因为一定要写 而是因为我觉得我是个小白...应该多多练习,大家如果是初学者的话也要这样哦~等我们也成为大佬了,自然也就不用了~[大佬不用看...])

📌 鼠标类

📌 键盘类

📌 笔记本类

📚 运行演示:

③ 接口的特性

📚 接口的特性有以下几点

📕 接口是一种抽象的引用类型,它不能直接实例化对象:

📕 接口可以定义方法,这些方法默认为 public abstract (使用其他修饰符会报错)

📕 接口可以包含常量,这些常量默认为 public static final,即常量的值在接口中被固定且不能被修改:

📕 重写接口中方法时,不能使用默认的访问权限:

📕 一个类只能继承一个父类,但可以实现多个接口:

📕 接口之间可以通过扩展(extends)实现接口的继承,一个接口可以扩展多个接口:

④ 接口的使用

那么学习了"接口",改如何体现它的重要作用呢?让我们通过一个案例来看看:

在"类与对象"的多篇文章学习中,我们举了很多很多次" 学生类 "

当我们把四个学生类放进一个数组中后,便不自觉地想到...我们之前学过一个Arrays.sort()方法,那么我们能否用Arrays.sort()方法对学生类数组进行排序呢

看来是没办法做到的,其实也不难理解,毕竟平时我们传进去的数组都有其自带的类型,int型呀,long型呀,double型呀他们也都有自己比较大小的规范,所以能够排序

而我们自己定义出来的Student,并没有规定的比较规范,所以sort方法也不知道,我们需要的排序到底是用"int",还是用"String",还是"double"...

这时我们就可以使用"接口"来实现这种"学生类的自定义排序"

实现Comparable接口,然后实现其中的compareTo方法:)

此时我们已经重写好了"compareTo"方法,然后我们再重写一下toString()方法,以便之后展示~

然后我们回到Main中

此时我们在使用Arrays.sort()就能够对学生类进行排序啦~

当然,毕竟是我们自己规定排序方法,所以除了用age进行排序,我们也可以用其他的进行排序

这样就能够对(成绩(double))进行排序啦~(compareTo的返回值需要是int)

如果怕(int)转换可能导致数据丢失,从而对比不准确,也可以这样

而为了加深对" compareTo "" Arrays.sort "方法的使用,我们可以自己实现一个sort函数(我们使用的是冒泡排序,当然Java底层不是冒泡排序,而是一种速度非常快的"快速排序")

仍然是可以运行的~

⑤ 深拷贝和浅拷贝

Java中内置了一些很有用的接口,Clonable就是其中一个

当我们直接使用clone()(克隆)方法时,我们发现是不能够做到的。

其实clone()方法我们并没有对其定义,也没有对其实现,所以它不在我们的子类当中。但是我们要知道,所有的类都有一个固定的,隐藏的父类->object类~而clone方法是在object类中的,所以我们没办法使用子类或子类对象去调用clone。

📚 当我们把" Clonable "接口接入Student类后,我们就可以尝试使用clone方法:

 

1.浅拷贝

顾名思义,就是"浅层次的拷贝",其意就是:

浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

📌 我们在此基础上创建一个Book类来辅助实验

然后我们观察两者的books值的变化

两者怎么都变成10了呢?这是因为

进行的一次clone()虽然出现了新的Student对象,但是我们只clone()了Student对象而Book是另一个类,并非完全属于Student,所以无法将books也独立的拷贝出来,而是"两者共用原来的books"

2.深拷贝

" 深层次的拷贝 "

📚 深拷贝把要复制的对象所引用的对象都复制了一遍

直接上图~

那么这篇关于(抽象类与接口)的知识,就暂时为大家分享到这里啦,作者能力有限,如果有哪里说的不够清楚或者不够简洁,还请大家在评论区多多指出,那么我们下期再见啦~


http://www.ppmy.cn/devtools/128550.html

相关文章

将jupyter中ipynb文件转成html文件

在VScode中使用jupyter(丘比特)时,将ipynb(我python牛比)后缀文件转成html时,总是报错: 那么可以就在需要转换的ipynb文件中,运行下面的代码,将“your_notebook”替换成同…

零基础Java第九期:一维数组(二)和二维数组

目录 一、数组的练习 1.1. 顺序表查找 1.2. 二分查找 1.3. 冒泡排序 二、二维数组 2.1. 二维数组的性质 2.2. 不规则二维数组 一、数组的练习 1.1. 顺序表查找 题目描述:给定一个数组, 再给定一个元素, 找出该元素在数组中的位置。 利用for循环去遍历数组&am…

未来医疗:大语言模型如何改变临床实践、研究和教育|文献精析·24-10-23

小罗碎碎念 这篇文章探讨了大型语言模型在医学领域的潜在应用和挑战,并讨论了它们在临床实践、医学研究和医学教育中的未来发展。 姓名单位名称(中文)Jan Clusmann德国德累斯顿工业大学埃尔朗根弗雷斯尼乌斯中心数字化健康研究所Jakob Nikola…

GitLab CVE-2024-6446、CVE-2024-6685 漏洞解决方案

极狐GitLab 近日发布安全补丁版本17.3.2, 17.2.5, 17.1.7,修复了17个安全漏洞,本分分享 CVE-2024-6446、CVE-2024-6685 两个漏洞详情及解决方案。 极狐GitLab 正式推出面向 GitLab 老旧版本免费用户的专业升级服务,为 GitLab 老旧版本进行专…

力扣动态规划基础版(斐波那契类型)

70. 爬楼梯https://leetcode.cn/problems/climbing-stairs/ 70.爬楼梯 方法一 动态规划 考虑转移方程和边界条件: f(x) f(x -1) f(x - 2);f(1) 1;f&…

数据结构 —— 链式二叉树(C语言讲解)

目录 0.前言 1.链式存储的二叉树 2.二叉树的遍历 二叉树的前、中、后序遍历 前序遍历 中序遍历 后序遍历 二叉树的层序遍历 3.二叉树的其他操作 二叉树的结点个数 二叉树叶子结点个数 二叉树第k层结点个数 二叉树查找值为x的节点 二叉树的高度 判断二叉树是否是…

【mysql进阶】2-4. mysql 系统库

mysql System Schema (mysql系统库) Mysql Schema是⼀个系统库,表中存储了MySQL服务器运⾏时所需的信息。⼴义上,mysqlschema包含存储数据库对象元数据的数据字典和⽤于其他操作⽬的的系统表。数据字典表和系统表位于数据⽬录下⼀个名为 mysql.ibd 的表…

【MySQL】详解MySQL数据类型

一、数据类型 各类型的数值范围: 在MySQL中,整型可以指定是有符号的和无符号的,默认是有符号的。 可以通过UNSIGNED来说明某个字段是无符号的。对于int类型可能存放不下的数据,尽量不使用unsigned,unsigned int 同样可…