当前位置: 首页 > news >正文

抽象类与接口的区别

抽象类

  1. 什么是抽象类?

抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。另外,抽象类可以派生自一个抽象类,可以覆盖基类的抽象方法也可以不覆盖,如果不覆盖,则其派生类必须覆盖它们。

  1. 如何定义抽象类?

  • 抽象类和抽象方法需要被 abstract 关键字修饰

  • 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体

举个例子:

/*** @author gf* @date 2023/2/23*/
// 1.抽象类和抽象方法需要被 abstract 关键字修饰
abstract  class Car {// 2.抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体abstract void makeCar();}
  1. 抽象类存在的意义?

众所周知,抽象类不能被实例化,那么抽象类存在的意义是什么呢?

抽象类存在的一个最大意义就是被继承,当被继承后就可以利用抽象类实现多态。

先看一段代码:

/*** @author gf* @date 2023/2/23*/// 抽象类和抽象方法需要被 abstract 关键字修饰
abstract  class Car {// 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体abstract void makeCar();
}class BWM extends Car{// 重写抽象类中的draw方法@Overridevoid makeCar() {System.out.println("制造宝马");}
}
public class CatTest {public static void main(String[] args) {// 抽象类虽然不能直接实例化,但可以把一个普通类对象传给一个抽象类的引用,即父类引用指向子类对象Car bwm = new BWM();// 通过父类引用调用被子类重写的方法bwm.makeCar();}
}

运行结果:

疑问1:父类引用指向子类对象后发生了什么?

  • 关于方法:父类引用可以 调用子类和父类公用的方法(如果子类重写了父类的方法,则调用子类方法)但子类特有的方法无法调用。

  • 关于属性: 父类引用可以调用父类的属性,不可以调用子类的属性

疑问2:这样做的好处是什么?

  • 减少一些重复性的代码

  • 对象实例化的时候可以根据不同需求实例化不同的对象

  1. 抽象类实现多态

再看一段代码:

// 抽象类和抽象方法需要被 abstract 关键字修饰
abstract  class Car {// 抽象类中的方法一般要求都是抽象方法,抽象方法没有方法体abstract void makeCar();
}class BWM extends Car{// 重写抽象类中的draw方法@Overridevoid makeCar() {System.out.println("宝马:即使你把我拆得七零八落,我依然是位美人");}
}
class Tesla  extends Car{// 重写抽象类中的draw方法@Overridevoid makeCar() {System.out.println("特斯拉:我要做电车界的老大");}
}class BYD  extends Car{// 重写抽象类中的draw方法@Overridevoid makeCar() {System.out.println("比亚迪:干掉特斯拉,我们就是电车界的老大");}
}
public class CatTest {public static void main(String[] args) {// 抽象类虽然不能直接实例化,但可以把一个普通类对象传给一个抽象类的引用,即父类引用指向子类对象Car bwm = new BWM();Car tesla = new Tesla();Car byd = new BYD();// 通过父类引用调用被子类重写的方法bwm.makeCar();tesla.makeCar();byd.makeCar();}
}

运行结果:

多态的好处这里就不赘叙了

疑问:抽象类实现多态和普通类实现多态有什么区别?

抽象类的子类必须重写父类的所有方法,而普通类则不用

  1. 抽象类的特点

信到这里对抽象类也有了一个大概的认识,下面我们来简单做一下总结

  1. 使用abstract修饰的类或方法,就抽象类或者抽象方法

  1. 抽象类是不能具体的描述一个对象,不能用抽象类直接实例化对象

  1. 抽象类里面的成员变量和成员方法,都是和普通类一样的,只不过就是不能进行实例化了

  1. 当一个普通类继承这个抽象类后,那么这个普通类必须重写抽象类当中的所有的抽象方法(我们之前说过抽象类是不具体的,没有包含足够的信息来描述一个对象,所以我们需要把他补充完整)

  1. 但当一个抽象类A继承了抽象类B,这是抽象类A就可以不重写抽象类B当中的抽象方法

  1. final不能修饰抽象类和抽象方法(因为抽象类存在的最大意义就是被继承,而被final修饰的不能被继承,final和抽象,他们两个是天敌)

  1. 抽象方法不能被private修饰(抽象方法一般都是要被重写的,你被private修饰了,还怎么重写)

  1. 抽象类当中不一定有抽象方法,但如果一个类中有抽象方法,那么这个类一定是抽象类。

接口

  1. 如何定义接口

  • 接口的定义格式与定义类的格式基本相同,将class关键字换成 interface 关键字,就定义了一个接口

  • 口当中的成员变量默认都是public static final

  • 接口当中的成员方法默认都是public abstract

例子:


public interface 接口名称{
// 定义变量,接口当中的成员变量默认都是public static final
int a = 10;    // 抽象方法
public abstract void method1(); // public abstract 是固定搭配,可以不写
void method2();  //  接口当中的成员方法默认都是public abstract, 更推荐用第二种来定义方法 
}

疑问:那么接口一般用在什么地方呢?

  • 一般情况下,实现类和它的抽象类之前具有 "is-a" 的关系,但是如果我们想达到同样的目的,但是又不存在这种关系时,使用接口。

  • 由于 Java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,此时可以使用接口。

  1. 通过接口实现多态

代码如下:


/*** @author gf* @date 2023/2/23*/interface  Car {void makeCar();
}class BWM implements Car{@Overridepublic void makeCar() {System.out.println("宝马:即使你把我拆得七零八落,我依然是位美人");}
}
class Tesla  implements Car{@Overridepublic void makeCar() {System.out.println("特斯拉:我要做电车界的老大");}
}class BYD  implements Car{@Overridepublic void makeCar() {System.out.println("比亚迪:干掉特斯拉,我们就是电车界的老大");}
}
public class CatTest {public static void main(String[] args) {Car bwm = new BWM();Car tesla = new Tesla();Car byd = new BYD();bwm.makeCar();tesla.makeCar();byd.makeCar();}
}

运行结果:

  1. 帮java实现多继承

由于 Java 中单继承的特性,导致一个类只能继承一个类,但是可以实现一个或多个接口,此时可以使用接口。

代码例子:

class Animal {String name;// 父类的自定义的构造方法public Animal(String name) {this.name = name;}
}
// 自定义多种接口
interface IFlying {void fly();
}
interface IRunning {void run();
}
interface ISwimming {void swimming();
}
// 小鸭子,不仅会跑,还会游泳、飞行
//一个类继承父类,并实现多个接口,间接的解决java中不能多继承的问题
class Duck extends Animal implements IRunning, ISwimming, IFlying {// 子类构造方法public Duck(String name) {super(name);// 在给实现子类的构造方法前,先要用super()调用实现父类的构造方法,比较先有父后有子呀!// 因为父类自己定义了构造方法,编译器不会自动给给子类构造方法中添加super();来实现父类的构造方法,需要我们自己实现}// 对接口中的抽象方法进行重写@Overridepublic void fly() {System.out.println(this.name + "正在用翅膀飞");}@Overridepublic void run() {System.out.println(this.name + "正在用两条腿跑");}@Overridepublic void swimming() {System.out.println(this.name + "正在漂在水上");}}public class CatTest {public static void main(String[] args) {Duck duck = new Duck("小黄鸭");  // 实例化鸭子对象duck.fly();  // 通过引用 变量名.方法名 输出重写后的方法duck.run();duck.swimming();}
}

疑问: 有人可能会说干嘛用接口,我直接在父类Animal中实现fly、run、swimming这些属性,

然后不同的动物子类再继承父类这些方法不行吗?

但问题是,鸭子会fly、swimming,那猫会飞和游泳吗?你再写个其他动物的子类是不是就不行了

而用接口呢?我们只是把这种飞、游泳的行为给抽象出来了,只要一个子类有这种行为,他就可以实现相对应的接口,接口是更加灵活的。

抽象类与接口的区别

通过以上对抽象类和接口的描述,我们总结一下抽象类和接口的区别

  1. 抽象类要被子类继承,接口要被类实现

  1. 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现

  1. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量

  1. 接口是设计的结果,抽象类是重构的结果

  1. 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高

  1. 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量

  1. 抽象类主要用来抽象类别,接口主要用来抽象功能

相关文章:

抽象类与接口的区别

抽象类什么是抽象类?抽象类是特殊的类,只是不能被实例化;除此以外,具有类的其他特性;重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现&#…...

1904. 你完成的完整对局数

题目: 一款新的在线电子游戏在近期发布,在该电子游戏中,以 刻钟 为周期规划若干时长为 15 分钟 的游戏对局。这意味着,在 HH:00、HH:15、HH:30 和 HH:45 ,将会开始一个新的对局,其中 HH 用一个从 00 到 23…...

Vue3:自定义指令以及简单的后台管理权限封装

目录 前言: 自定义指令介绍: 局部的自定义指令: 全局自定义指令: 讲讲后台管理权限管理: 前言: 说起这个自定义指令的使用场景,我第一反应就是,后台管理的权限管理,要…...

剑指 Offer 12. 矩阵中的路径

摘要 剑指 Offer 12. 矩阵中的路径 一、回溯算法解析 本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS) 剪枝解决。 深度优先搜索: 可以理解为暴力法遍历矩阵中所有字符串可能性。DFS 通过递归,先朝一个方向搜…...

springboot+jersey+tomcat实现跨域方式上传文件到服务器

前言 在服务器上,当我们启动了tomcat,就可以以 http://ip地址:8080/文件路径/文件名 的方式,进行访问到我们服务器上处于tomcat的webapps文件夹下的文件 于是为了可以往上面加文件,我们有两种方式,一种就是直接复制文…...

【微信小程序】-- 常用视图容器类组件介绍 -- view、scroll-view和swiper(六)

💌 所属专栏:【微信小程序开发教程】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &#…...

猜数字游戏——C++

我们在有了一定的C基础了以后,简单的实现一个案例(其实只要会while循环结构就行了),我们本章内容会实现猜数字游戏,大家有什么语法疑问可以看看我写的:C快速入门_染柒_GRQ的博客-CSDN博客,该博客…...

整数对最小和

题目描述 给定两个整数数组 array1 array2。数组元素按升序排列,假设从array1 、array2中分别取出一个元素可构成一对元素,现在需要取出K个元素并对取出的所有元素求和,计算和的最小值 注意事项 两对元素如果对应于array1 array2中的两个下…...

2023-2-22 -javaagent

周三,天气晴,7度 Java Agent Java Agent也叫作java探针,可以实现动态修改java字节码,完成额外的功能。在java类编译成字节码,在jvm执行之前,它可以读取修改字节码,以来完成额外的功能。 使用…...

JavaScript BOM操作

目录 前言 window 对象 location 对象 navigator 对象 screen 对象 history 对象 前言 BOM(Browser Object Model)指的是浏览器对象模型,它是 JavaScript 和浏览器之间的接口。通过 BOM,JavaScript 可以与浏览器窗口交互&…...

【机器学习 | 强基计划】开山篇 | 机器学习介绍及其类别和概念阐述

🤵‍♂️ 个人主页: @计算机魔术师 👨‍💻 作者简介:CSDN内容合伙人,全栈领域优质创作者。 机器学习 | 强基计划系列 (一) 作者: 计算机魔术师 版本: 1.0 ( 2022.2.25) 注释:文章会不定时更新补充 文章目录 前言一、机器学习概览1.1 有监督学习和无监督学习1.1.…...

华为OD机试真题Java实现【合规数组】真题+解题思路+代码(20222023)

合规数组 题目 给定一个正整数数组 检查数组中是否存在满足规则的数组组合 规则: A = B + 2C 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Java)真题目录汇总 ## 输入 第一行输出数组的元素个数 接下来一行输出所有数组元素,用空格隔开 输出 如果存在满…...

BoostSearcher搜索引擎项目

BoostSearcher搜索引擎项目 1.BoostSearcher这个项目是什么? 答:一个为Boost文档建立索引的站内搜索引擎,简单的说就是一个类似于csdn站内文档搜索框。 项目展示: gitee:https://gitee.com/zxlfx/boost-search-engine-project …...

【模拟集成电路】频率综合器(Frequency Synthesizer,FS)设计

应用于无线局域网的频率综合器设计前言频率综合器简介各部分链接链接:前言 本文主要内容是对频率综合器或称为PLL 做出简单介绍,为课程设计部分章节内容,后需给出各部分的设计方案,以及测试结果。 频率综合器简介 无线收发系统中…...

实例8:机器人的空间描述和变换仿真

实例8:机器人的空间描述和变换仿真 实验目的 通过刚体与刚体的平动、转动基础知识的学习,熟悉位姿的描述通过Python编程实践,可视化学习坐标系的变换,熟悉空间变换 实验要求 通过python编程,输入一指定向量和对应的…...

网络 导航

目录内容链接网络网络参考文章:【网络】http请求 调试网络问题解决参考文章:【问题解决】网络 IP DNS解析网络问题解决参考文章:【问题解决】网络 TCP 规则 抓包网络问题解决参考文章:【问题解决】网络 Http请求 调试网络问题解决…...

Web Spider Ast-Hook 浏览器内存漫游-数据检索

文章目录一、资源下载二、通过npm安装anyproxy模块三、anyproxy的介绍以及基本使用1. anyproxy的功能介绍2. anyproxy的基本使用四、给浏览器挂代理五、实操极验demo案例总结提示:以下是本篇文章正文内容,下面案例可供参考 一、资源下载 Github&#x…...

计算机网络笔记、面试八股(二)——HTTP协议

本章目录2. HTTP协议2.1 HTTP协议简介2.2 HTTP协议的优点2.3 HTTP协议的缺点2.4 HTTP协议属于哪一层2.5 HTTP通信过程2.6 常见请求方法2.7 GET和POST的区别2.8 请求报文与响应报文2.8.1 HTTP请求报文2.8.2 HTTP响应报文2.9 响应状态码2.10 HTTP 1.0和1.1的区别2.10.1 长连接2.1…...

docker快速上手使用

文章目录一、docker概述1. 为什么需要docker2. 什么是docker3. docker和虚拟机的区别4. docker三要素二、docker安装1. 添加app源2. 安装docker社区版3. 更换国内docker镜像源三、docker基本使用方法1. 获取镜像2. 查看当前系统中的docker镜像3. 运行docker容器4. 查看当前存在…...

<c++> 类的构造函数与类的析构函数

文章目录类的构造函数什么是构造函数声明和定义构造函数如何使用构造函数默认构造函数类的析构函数什么是析构函数声明和定义析构函数小练习银行账户执行效果类的构造函数 什么是构造函数 Q:什么是类的构造函数 A:构造函数是类的一种特殊成员函数,不需…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...