Java-抽象类和接口

一、抽象类

① 抽象类的概念

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

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

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

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

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

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

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

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

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

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

② 抽象类的实现

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

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

📕 抽象类"Animal"

📕 继承"Animal"的子类们

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

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

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

正常运行

③ 抽象类的特征

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

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

📕 抽象方法不能是 private 的:

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

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

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

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

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

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

二、接口

① 接口的概念

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

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

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

由此可以得出结论

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

② 接口的实现

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

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

📚 代码格式:

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.深拷贝

" 深层次的拷贝 "

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

直接上图~

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

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值