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

第二十条:与抽象类相比,优先选择接口

要定义多种实现的类型:JAVA有两种机制:接口和抽象类。这两种机制都支持为某些实例方法提供实现,但二者有个重要的区别:要实现由抽象类定义的类型,这个类必须是抽象类的子类。因为Java只允许单继承,对抽象类的这种限制严重制约了将其用于类型的定义。而接口就宽松很多,只要定义了所有必须的方法,任何类都可以实现。

在正式介绍之前普及两个知识点:缺省方法和抽象方法。

这两个方法是相反的用途:缺省是为了避免子类重写其方法。抽象方法是为了让子类重写方法。

缺省方法(default)案例:

public interface SoyaMilk2 {default void select() {System.out.println("选择");}
}

子类:

public class RedInter implements SoyaMilk2 {}

抽象方法案例:

public interface SoyaMilk2 {abstract void addCondiments();}

子类:

接口优先于抽象类优点:

1.很容易改造现有的类使其实现一个新的接口。

2.接口是定义minxin(混合类型)的理想选择。

3.接口允许构建非层次结构的类型框架。

案例:

public interface Singer {//唱歌AudioClip sing(Song s);
}public interface SongWriter {//作歌Song compose(boolean hit);
}
public intreface SingerSongWriter extends Singer, SongWriter {//弹奏AudioClip strum();//激情表演void actSensitive();
}

抽象类:

Singer.java
public abstract class Singer {//唱歌public abstract AudioClip sing(Song s);
}SongWriter.java
public abstract class SongWriter {//作歌public abstract Song compose(boolean hit);
}SingerSongWriter.java
//在设计的时候感觉很不好设计。因为继承只能继承自一个类,那势必其他的方法需要重新声明
public abstract class SingerSongWriter extends SongWriter {//唱歌public abstract AudioClip sing(Song s);//弹奏public abstract AudioClip strum();//激情表演public abstract void actSensitive();
}

在引入抽象骨架概念之前,先分别看下接口和抽象类的案例实现:

(1)接口案例:

定义接口:

public interface IPeple {void drink();void eat();void ethnicGroup();}

分别定义子类:

public class AsiaPeple implements IPeple {@Overridepublic void drink() {System.out.println("人都会喝水");}@Overridepublic void eat() {System.out.println("人都会吃饭");}@Overridepublic void ethnicGroup() {System.out.println("亚洲人大多数是黄种人");}
}
public class AmericanPeple implements IPeple {@Overridepublic void drink() {System.out.println("人都会喝水");}@Overridepublic void eat() {System.out.println("人都会吃饭");}@Overridepublic void ethnicGroup() {System.out.println("美洲人大多数是白种人");}
}

问题:

drink和eat方法代码重复性很高,需要改造。

(2)抽象类案例:

定义抽象类:

public abstract class AbsPeple {void drink(){System.out.println("人都会喝水");}void eat() {System.out.println("人都会吃饭");}abstract void ethnicGroup();
}

分别定义子类:

public class AmericanPeple extends AbsPeple {@Overridevoid ethnicGroup() {System.out.println("美洲人大多数是白种人");}
}

public class AsiaPeple extends AbsPeple{@Overridevoid ethnicGroup() {System.out.println("亚洲人大多数是黄种人");}public static void main(String[] args) {AsiaPeple asiaPeple = new AsiaPeple();asiaPeple.eat();asiaPeple.drink();asiaPeple.ethnicGroup();AmericanPeple americanPeple = new AmericanPeple();americanPeple.eat();americanPeple.drink();americanPeple.ethnicGroup();System.out.println(asiaPeple);System.out.println(americanPeple);}
}

结果打印:

人都会吃饭
人都会喝水
亚洲人大多数是黄种人
人都会吃饭
人都会喝水
美洲人大多数是白种人
com.example.exceldemo.abstact.entity.AsiaPeple@7699a589
com.example.exceldemo.abstact.entity.AmericanPeple@58372a00

缺点:一旦一个类继承了抽象类AbsPeple,那么它就无法继承其它类。而且我们也知道,继承实现有很多问题,太多的继承会造成代码耦合性问题,不利于以后的维护和升级。抽象骨架氤氲而生。

(3)抽象骨架概念:(抽象类继承接口,不要求重写接口中缺省、抽象方法)

可以将接口和抽象类的优点结合到一起。其中,接口用来定义类型,可能还会提供一些默认的方法,而骨架实现类负责在基本接口方法之上实现其余的非基本接口方法(ethnicGroup()方法)。扩展骨架实现类可以省去实现接口需要的大部分工作。这就是模板方法【设计模式】(中级面试很多面试官喜欢问设计模式)

定义抽象骨架:

public abstract class AbsPeple implements IPeple{@Overridepublic void drink() {System.out.println("人都要喝水");}@Overridepublic void eat() {System.out.println("人都要吃饭");}
}

定义私有类及成员(AsiaPeple重写接口统一方法,成员变量获取单独的重写方法):

public class AsiaPeple implements IPeple {private AsiaPepleIpml asiaPepleIpml = new AsiaPepleIpml();private static class AsiaPepleIpml extends AbsPeple {@Overridepublic void ethnicGroup() {System.out.println("亚洲人大多数都是黄种人");}}public static void main(String[] args) {AsiaPeple asiaPeple = new AsiaPeple();asiaPeple.eat();asiaPeple.drink();asiaPeple.asiaPepleIpml.ethnicGroup();}@Overridepublic void drink() {asiaPepleIpml.drink();}@Overridepublic void eat() {asiaPepleIpml.eat();}@Overridepublic void ethnicGroup() {throw new UnsupportedOperationException("不重新方法");}
}

打印结果:

人都要吃饭
人都要喝水
亚洲人大多数都是黄种人Process finished with exit code 0

AsiaPeple类 可以实现多个接口和定义多个抽象骨架实现类,使得AsiaPeple类非常非常灵活多变。

骨架实现类的美妙在于,他们提供了抽象类的所有实现帮助,又不存在将抽象类用于类型定义时所面临的严格限制。接口本身存在的任何默认方法,对于这个类还是有帮助的。此外,仍然可以利用骨架实现来帮助实现者完成任务:实现该接口的类可以引入一个私有的、扩展了骨架实现类的内部类,并包含一个这个内部类实例,然后将对接口方法的调用转发给这个实例。这种技术被称为模拟多重继承。

因为骨架实现是为了继承而设计的,好的文档在骨架实现中是绝对必要的,无论它是由接口上的默认方法组成还是单独的抽象类。

总而言之,要定义支持实现的类型,接口通常是最佳选择如果导出一个不是很简单的接口,请务必考虑配合提供一个骨架实现。在可能的情况下,应该通过接口上的默认方法来提供骨架的实现,以便该接口的所有实现者都可以使用。即便如此,接口上的限制常会使得抽象类形式成为骨架实现的不二之选。

所有文章无条件开放,顺手点个赞不为过吧!

                                                               

相关文章:

第二十条:与抽象类相比,优先选择接口

要定义多种实现的类型:JAVA有两种机制:接口和抽象类。这两种机制都支持为某些实例方法提供实现,但二者有个重要的区别:要实现由抽象类定义的类型,这个类必须是抽象类的子类。因为Java只允许单继承,对抽象类…...

20240705

Nacos Service Discovery 通过nacos实现的服务发现平台 Spring Cloud Alibaba Sentinel 提供 Sentinel 自动接入和配置支持,提供 Spring Web/WebFlux、Feign、RestTemplate、注解等适配 Spring Cloud Alibaba Sentinel DataSource 提供 Sentinel 动态数据源接入支…...

【2023ICPC网络赛I 】E. Magical Pair

当时在做洛谷U389682 最大公约数合并的时候我就想到把每个质因子分解出来然后跑高维前缀和,但是那一道题不是用这个方法,所有我也一直在思考这种做法是不是真的有用。因为昨天通过2024上海大学生程序设计竞赛I-六元组计数这道题我了解到了不少关于原根的…...

Kafka-服务端-网络层-源码流程

整体架构如下所示: responseQueue不在RequestChannel中,在Processor中,每个Processor内部有一个responseQueue 客户端发送的请求被Acceptor转发给Processor处理处理器将请求放到RequestChannel的requestQueue中KafkaRequestHandler取出reque…...

百日筑基第十一天-看看SpringBoot

百日筑基第十一天-看看SpringBoot 创建项目 Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下: https://start.spring.io/ 打开后的界面如下: 可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导&#xff…...

Generative Modeling by Estimating Gradients of the Data Distribution

Generative Modeling by Estimating Gradients of the Data Distribution 本文介绍宋飏提出的带噪声扰动的基于得分的生成模型。首先介绍基本的基于得分的生成模型的训练方法(得分匹配)和采样方法(朗之万动力学)。然后基于流形假…...

vector与list的简单介绍

1. 标准库中的vector类的介绍: vector是表示大小可以变化的数组的序列容器。 就像数组一样,vector对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问其元素,并且与数组中的元素一样高效。但与数…...

四种线程池的使用,优缺点分析

池化思想:线程池、字符串常量池、数据库连接池 提高资源的利用率 下面是手动创建线程和执行任务过程,可见挺麻烦的,而且线程利用率不高。 手动创建线程对象执行任务执行完毕,释放线程对象 线程池的优点: 提高线程的…...

什么是 BEM 规范

BEM(Block, Element, Modifier)是一种 CSS 命名规范,旨在提高代码的可读性和可维护性。BEM 规范通过明确的命名规则来定义组件和组件的各个部分,使开发者能够更容易地理解和维护代码。 BEM 命名规范的基本概念 Block&#xff08…...

【Node.JS】入门

文章目录 Node.js的入门涉及对其基本概念、特点、安装、以及基本使用方法的了解。以下是对Node.js入门的详细介绍: 一、Node.js基本概念和特点 定义:Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它使得JavaScript能够运行在服务器…...

Amazon SageMaker 机器学习之旅的助推器

一、前言 在当今的数字化时代,人工智能和机器学习已经成为推动社会进步的重要引擎。亚马逊云科技在 2023 re:Invent 全球大会上,宣布推出五项 Amazon SageMaker 新功能: Amazon SageMaker HyperPod 通过为大规模分布式训练提供专用的基础架构…...

TransMIL:基于Transformer的多实例学习

MIL是弱监督分类问题的有力工具。然而,目前的MIL方法通常基于iid假设,忽略了不同实例之间的相关性。为了解决这个问题,作者提出了一个新的框架,称为相关性MIL,并提供了收敛性的证明。基于此框架,还设计了一…...

3.用户程序与驱动交互

驱动程序请使用第二章https://blog.csdn.net/chenhequanlalala/article/details/140034424 用户app与驱动交互最常见的做法是insmod驱动后,生成一个设备节点,app通过open,read等系统调用去操作这个设备节点,这里先用mknode命令调…...

尽量不写一行if...elseif...写出高质量可持续迭代的项目代码

背景 无论是前端代码还是后端代码,都存在着定位困难,不好抽离,改造困难的问题,造成代码开发越来越慢,此外因为代码耦合较高,总是出现改了一处地方,然后影响其他地方,要么就是要修改…...

xcrun: error: unable to find utility “simctl“, not a developer tool or in PATH

目录 前言 一、问题详情 二、解决方案 1.确认Xcode已安装 2.安装Xcode命令行工具 3.指定正确的开发者目录 4. 确认命令行工具路径 5. 更新PATH环境变量 前言 今天使用cocoapods更新私有库的时候,遇到了"xcrun: error: unable to find utility &…...

【linux高级IO(一)】理解五种IO模型

💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:Linux从入门到精通⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学更多操作系统知识   🔝🔝 Linux高级IO 1. 前言2. 重谈对…...

前端引用vue/element/echarts资源等引用方法Blob下载HTML

前端引用下载vue/element/echarts资源等引用方法 功能需求 需求是在HTML页面中集成Vue.js、Element Plus(Element UI的Vue 3版本)、ECharts等前端资源,使用Blob下载HTML。 解决方案概述 直接访问线上CDN地址:简单直接&#xff0c…...

昇思MindSpore学习笔记2-01 LLM原理和实践 --基于 MindSpore 实现 BERT 对话情绪识别

摘要: 通过识别BERT对话情绪状态的实例,展现在昇思MindSpore AI框架中大语言模型的原理和实际使用方法、步骤。 一、环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14,如需更换mindspore版本,可更改下…...

uniapp实现图片懒加载 封装组件

想要的效果就是窗口滑动到哪里&#xff0c;哪里的图片进行展示 主要原理使用IntersectionObserver <template><view><image error"HandlerError" :style"imgStyle" :src"imageSrc" :id"randomId" :mode"mode&quo…...

持续交付:自动化测试与发布流程的变革

目录 前言1. 持续交付的概念1.1 持续交付的定义1.2 持续交付的核心原则 2. 持续交付的优势2.1 提高交付速度2.2 提高软件质量2.3 降低发布风险2.4 提高团队协作 3. 实施持续交付的步骤3.1 构建自动化测试体系3.1.1 单元测试3.1.2 集成测试3.1.3 功能测试3.1.4 性能测试 3.2 构建…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...