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

抽象类实现接口的意义

文章目录

  • 前言
  • 一、抽象类和接口对比
  • 二、举例说明三种情况
    • 1.接口实现类
      • 接口
    • 2.抽象类实现类
      • 抽象类
      • 实现类(子类)
    • 3.抽象类实现接口
      • 接口
      • 抽象类
      • 三个实现类
  • 总结


前言

抽象类和接口其实都是抽象的一种,那么他俩有何异同呢?
抽象类实现接口的意义何在?


一、抽象类和接口对比

  1. 接口大家比较熟悉,它其实是一种规范,规定了方法的入参,反参等,一种抽象, 关键字是 interface;
  2. 抽象类是用 abstract 修饰的类,可以包含抽象方法,也可以不包含抽象方法,可以有普通方法
  3. 一般来说接口中的方法都是抽象的,无方法体的,但是java8之后,增加了default (大家课后了解下),它让接口也可以有方法体了,那么其实这里的default 就增强了接口的功能,不逊于抽象类了;
  4. 接口是用来实现的,而且实现一个接口的时候,子类必须实现接口中的所有方法
  5. 抽象类是用来被继承的,抽象类中的抽象方法可以在子类中选择性实现,这就是抽象类的灵活性
  6. 那么当我用抽象类实现接口,我可以选择某些方法我在抽象类中实现,某些方法我不实现,而是继续在抽象类的子类中实现,那么这个方法我虽然实现了,但是还是一个抽象方法(你以为我实现了,然后并没有)

没有代码,仅讲解的的博主相当于耍流氓,接下来进入代码环节

二、举例说明三种情况

1.接口实现类

使用场景: 我又两种支付方式,微信/支付宝, 为了统一对外逻辑,我弄成一个接口对外暴露,方便统一调用

接口

public interface PayService {/*** 获取支付具体实现** @return*/String getType();/*** 具体支付方法** @param order* @param money* @return*/String toPay(String order, Integer money);
}### 实现类
```java 
@Service
public class AliPayServiceImpl implements PayService {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "Ali";}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("阿里支付用支付宝,优惠一元");return "Ali支付 订单号: " + order + " 金额: " + (money - 1);}
}// =======================================================@Service
public class WxPayServiceImpl implements PayService {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "Wx";}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("微信支付,原价支付");return "Wx支付 订单号: " + order + " 金额: " + money;}
}

2.抽象类实现类

使用场景: 依然是第一个支付场景,我这里简单改造下;抽象类还能有普通方法,这里我增加一个支付打印

抽象类

public abstract class PayService {/*** 获取支付具体实现** @return*/abstract String getType();/*** 具体支付方法** @param order* @param money* @return*/abstract String toPay(String order, Integer money);/*** 支付成功打印*/public void sout(){System.out.println("我支付成功了");}
}

实现类(子类)

@Service
public class AliPayServiceImpl extends PayService {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "Ali";}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("阿里支付用支付宝,优惠一元");return "Ali支付 订单号: " + order + " 金额: " + (money - 1);}
}// =========================================================
@Service
public class WxPayServiceImpl extends PayService {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "Wx";}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("微信支付,原价支付");return "Wx支付 订单号: " + order + " 金额: " + money;}
}

这里看完是不是觉得抽象比接口强大,那为什么还要接口呢?

  • 接口可以解决多重继承问题,提供更灵活的扩展和维护
  • Java中的抽象类和接口各有其应用场景,抽象类和接口都可以定义规范,但实现规范的方式不同。抽象类是具体实现的规范,而接口是行为的规范。
  • 抽象类可以解决单继承局限,避免多继承带来的复杂性和低效性

3.抽象类实现接口

使用场景: 仍然是支付场景,接口中定义了四个方法 (abcd),有三个实现类 A B C ;
其中A 需要实现 ab d, B需要实现 bc d, C需要实现ca d
也就是A B C 三个实现类不需要实现接口中的所有方法,但是都需要实现d方法,而且是一个逻辑
这里d方法在每个子类中都实现一遍没必要,重复代码,咋办呢? 我们在接口和实现类之间加一个 抽象类

接口

public interface PayService {/*** 获取支付具体实现** @return*/String getType();/*** 具体支付方法** @param order* @param money* @return*/String toPay(String order, Integer money);/*** 扣减库存* @param num 购买数量* @return*/int decreaseStash(int num);/*** 打印成支付*/void sout();}

抽象类

public abstract class PayAbstract implements PayService{/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return null;}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {return null;}/*** 扣减库存** @param num 购买数量* @return*/@Overridepublic int decreaseStash(int num) {return 0;}/*** 打印成支付*/@Overridepublic void sout() {System.out.println("支付成功");}
}

三个实现类

@Service
public class AliPayServiceImpl extends PayAbstract {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "Ali";}/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("阿里支付用支付宝,优惠一元");return "Ali支付 订单号: " + order + " 金额: " + (money - 1);}
}// ============================================================
@Service
public class WxPayServiceImpl extends PayAbstract {/*** 具体支付方法** @param order* @param money* @return*/@Overridepublic String toPay(String order, Integer money) {System.out.println("微信支付,原价支付");return "Wx支付 订单号: " + order + " 金额: " + money;}/*** 扣减库存** @param num 购买数量* @return*/@Overridepublic int decreaseStash(int num) {return num;}
}// ============================================================@Service
public class JUHEPayServiceImpl extends PayAbstract {/*** 获取支付具体实现** @return*/@Overridepublic String getType() {return "JUHE";}/*** 扣减库存** @param num 购买数量* @return*/@Overridepublic int decreaseStash(int num) {return num;}
}

这样在接口和抽象类之间又做了一层抽象,抽象层提取了公共的方法d (sout),而且让每个实现类都更加灵活的实现方法


总结

抽象类实现接口的意义在于提供了一种灵活且层次分明的代码结构,有助于实现模块化和可维护性。

具体来说,抽象类可以作为继承层次结构中的基础类,提供一些公共方法和属性,子类可以继承和扩展。而接口则定义了一组相关的方法规范,约束了实现这些方法的类或抽象类的行为。这有助于确保代码的模块化,提高代码的可重用性和可维护性。

抽象类相当于在原有抽象的基础上,再次抽象,提取了一些公共方法;

相关文章:

抽象类实现接口的意义

文章目录 前言一、抽象类和接口对比二、举例说明三种情况1.接口实现类接口 2.抽象类实现类抽象类实现类(子类) 3.抽象类实现接口接口抽象类三个实现类 总结 前言 抽象类和接口其实都是抽象的一种,那么他俩有何异同呢? 抽象类实现接口的意义何在? 一、抽象类和接口对比 接口…...

什么是接口测试,如何做接口测试?

比起点点点的功能测试,“接口测试”显得专业又高大上,也因此让有些初级测试人员“望而生畏”。别担心,其实接口测试也是功能测试的一种,它是针对接口进行的功能测试。 写在前面:本文参考了茹炳晟老师的《测试工程师 全…...

Keil 编译 Debug

# 头文件无法导入进来 # 导入头文件,只有函数声明,但缺少函数实现 已经导入了air32f10x_gpio.h但是没有导入 .c,就导致 编译出错出现undefined symbol (某个函数),这时候按照下面的操作,导入外设模块就好。...

【通用消息通知服务】0x3 - 发送我们第一条消息(Websocket)

【通用消息通知服务】0x3 - 发送我们第一条消息 项目地址: A generic message notification system[Github] 实现接收/发送Websocket消息 Websocket Connection Pool import asyncio from asyncio.queues import Queue from asyncio.queues import QueueEmpty from contextli…...

Eclipse打jar包与JavaDOC文档的生成

补充知识点——Eclipse打jar包与JavaDOC文档的生成 1、Eclipse如何打jar包,如何运行jar包 Java当中编写的Java代码,Java类、方法、接口这些东西就是项目中相关内容,到时候我们需要把代码提供给甲方、或者是我们需要运行我们编写的代码&…...

力扣:80. 删除有序数组中的重复项 II(Python3)

题目: 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下…...

linux:需要注意docker和aws的rds的mysql默认是UTC而不是中国时区

问题: 如题 解决办法: docker参考: mysql时间不对,修改时区_set global time_zone 无效_《小书生》的博客-CSDN博客 aws参考: https://www.youtube.com/watch?vB-NaqV-A1BY mysql - AWS修改RDS时区 - 个人文章 - Segm…...

访问 GitHub 方法

访问 GitHub 方法 方法一:最常见的就是 fq,但这个是违法的行为,自己私下搞可以,不能教你们。 方法二:利用加速器,这是正规合法操作。这里推荐一个免费的加速器,下载安装 Watt Toolkit加速器,原名…...

旅游APP外包开发注意事项

旅游类APP通常具有多种功能,以提供给用户更好的旅行体验。以下分享常见的旅游类APP功能以及在开发和使用这些APP时需要注意的问题,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 常见功能…...

ROS机器人编程---------(二)ROS中的核心概念

ROS机器人编程 ROS中的核心概念 ROS的通信机制 在ROS中结点是最小单元,比如说机器人的遥控器可以作为一个控制结点,机器人上的摄像头也可以看作一个结点,ROS通过协调各个结点来实现 在启动任何ROS结点之前,都必须先启动ROS Mas…...

Python学习教程:进程的调度

前言 嗨喽~大家好呀,这里是魔王呐 ❤ ~! 要想多个进程交替运行,操作系统必须对这些进程进行调度, 这个调度也不是随即进行的,而是需要遵循一定的法则,由此就有了进程的调度算法。 python更多源码/资料/解答/教程等 …...

ElasticSearch第三讲:ES详解 - Elastic Stack生态和场景方案

ElasticSearch第三讲:ES详解 - Elastic Stack生态和场景方案 本文是ElasticSearch第三讲,在了解ElaticSearch之后,我们还要了解Elastic背后的生态 即我们常说的ELK;与此同时,还会给你展示ElasticSearch的案例场景&…...

基于Java+SpringBoot+Vue前后端分离农商对接系统设计和实现

博主介绍:✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专…...

【模方ModelFun】实景三维建模和修模4.0.7最新版安装包以及图文安装教程

模方ModelFun 具有多种功能,旨在帮助用户进行实景三维建模和修模。以下是一些主要功能的简要介绍: 实景三维建模:【模方ModelFun】提供了自动化的实景三维重建功能,可以从实景图像中提取几何形状和纹理信息,生成高质量…...

介绍几个搜索引擎

Google:全球最大的搜索引擎,提供全面的搜索服务,包括网页、图片、视频、新闻、地图等。 Baidu:中国最大的搜索引擎,提供类似于Google的全面搜索服务,同时也有网盘、知道等功能。 Bing:微软公司…...

iPhone 隔空投送使用指南:详细教程

本文介绍了如何在iPhone上使用隔空投送,包括如何在iOS 11到iOS 14的iPhone上启用它、发送文件以及接受或拒绝AirDrop发送给你的文件。对于iOS 7以上的旧款iPhone,提供了另一种方法。 如何打开隔空投送 你可以通过以下两种方式之一启动隔空投送功能:在“设置”应用程序或控…...

百度文心一言GPT免费入口也来了!!!

文心一言入口地址:文心一言能力全面开放 文心一言是百度全新一代知识增强大语言模型,文心大模型家族的新成员,能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。 文心一言的技…...

线程调度和线程控制

在Java中,线程调度和线程控制是多线程编程中重要的概念,它们用于管理和控制线程的执行。以下是关于线程调度和线程控制的一些重要概念和技术: **1. 线程调度(Thread Scheduling): ** 线程调度是操作系统或Java虚拟机决定哪个线程在何时执行的过程。Java提供了多种线程调度…...

laravel excel导入导出

一、安装第三方 composer require maatwebsite/excel版本2.1和现在版本 有所不一样 二、导入 <?php namespace App\Import; use Maatwebsite\Excel\Concerns\ToCollection;class TestImport implements ToCollection {public function __construct(){}public function c…...

Windows无法删除分区怎么办?

我们知道Windows系统内置的磁盘管理工具是一个很实用的程序&#xff0c;可以帮助我们完成很多磁盘分区相关的基础操作&#xff0c;比如当我们想要删除硬盘上的某一个分区时&#xff0c;先想到的可能会是磁盘管理工具。但是当我们准备在磁盘管理工具中删除某个分区时&#xff0c…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Python 高效图像帧提取与视频编码:实战指南

Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

32位寻址与64位寻址

32位寻址与64位寻址 32位寻址是什么&#xff1f; 32位寻址是指计算机的CPU、内存或总线系统使用32位二进制数来标识和访问内存中的存储单元&#xff08;地址&#xff09;&#xff0c;其核心含义与能力如下&#xff1a; 1. 核心定义 地址位宽&#xff1a;CPU或内存控制器用32位…...

Springboot 高校报修与互助平台小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;高校报修与互助平台小程序被用户普遍使用&#xff0c;为…...