面向对象中接口(亦称: 协议、protocol、 “鸭子类型”)与抽象类

news2024/11/16 11:46:57

在这里插入图片描述

接口与类相比

在这里插入图片描述

由编译器强制的一个模块间协作的合约(Contract):

接口是一个由编译器强制的模块间协作的合约。它定义了一组方法的契约,所有实现该接口的类都必须提供这些方法的具体实现。这种强制性保证了不同模块之间的协作方式的一致性和可靠性。举例来说,Java 中的 List 接口定义了一组列表操作的方法,如 addgetremove 等,所有实现了 List 接口的类都必须提供这些方法的具体实现。

无成员变量:

接口不能包含任何成员变量,它只能包含方法的声明。这是因为接口的目的是定义一组方法的契约,而不关心具体的实现和状态。因此,接口中只能声明方法,而不能包含任何与状态相关的成员变量。相比之下,类可以包含成员变量,因为类除了定义方法外,还可以包含状态和行为的具体实现。

成员函数只有申明不能有实现:

接口中的方法只能有声明而不能有具体的实现。这是因为接口是一种纯粹的抽象,它只定义了一组方法的契约,而不关心具体的实现。因此,接口中的方法只能有方法的签名,而不能包含方法的具体实现。相比之下,类中的方法可以有具体的实现,因为类除了定义方法签名外,还可以提供方法的具体实现。

在这里插入图片描述

接口的声明

静态语言角度(Java、TypeScript)依赖关键字:

在静态类型语言中,如Java和TypeScript,接口的声明通过关键字来实现。具体来说:

  • Java 中使用 interface 关键字声明接口,然后在类中通过 implements 关键字实现接口。
  • TypeScript 中也使用 interface 关键字声明接口,然后可以通过 implements 关键字或者直接在类中定义相同的结构来实现接口。

通过关键字的方式,编译器可以在编译时检查类是否实现了接口中定义的所有方法,以及方法的参数和返回值类型是否匹配。

动态语言角度(JavaScript、Python)依赖注释文档约束:

在动态类型语言中,如JavaScript和Python,接口的约束主要依赖于注释文档和约定。具体来说:

  • JavaScript 中通常使用 JSDoc 注释来描述接口和方法的结构和用法,然后通过开发者的遵循来保证类的实现符合接口的契约。
  • Python 中没有内置的接口机制,但通常通过注释文档或者约定来定义接口,然后由开发者自觉遵守这些约定。

在动态语言中,接口的实现没有严格的语法规定,更多地依赖于开发者的自觉和约定。虽然没有编译器在编译时检查,但可以通过代码审查和单元测试等方式来确保类的实现符合接口的要求。

Go 用鸭子类型实现类时接口功能:

Go 语言中没有传统意义上的接口,但通过鸭子类型(Duck Typing)来实现接口的功能。鸭子类型是一种动态类型系统中的一种策略,它关注对象的行为而不是对象的类型。

在 Go 中,一个类型只要实现了某个接口所定义的所有方法,就可以被视为实现了该接口。这种方式类似于动态语言中的接口约定,但更加灵活,没有明确的接口声明和实现关系。

通过鸭子类型,Go 语言可以实现接口的功能,但在语法上与静态类型语言中的接口有所不同。

面试题:接口和抽象类的不同

抽象类可以有成员变量:

在 Java 中,抽象类可以包含成员变量,而接口不能包含任何成员变量。这意味着抽象类可以包含具体的状态和行为,而接口只能包含方法的声明。举例来说,AbstractList 类就包含了一些成员变量来管理列表的状态,比如 modCountsize

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    protected transient int modCount = 0;
    protected int size;
}

抽象类可以有部分实现:

抽象类可以有部分方法的实现,而接口中的方法都是抽象的,没有具体的实现。这意味着在抽象类中,可以将一些通用的方法实现在抽象类中,而在子类中实现特定的行为。举例来说,AbstractList 类中实现了 toString() 方法和 isEmpty() 方法。

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }

    public boolean isEmpty() {
        return size() == 0;
    }
}

抽象类不可以多重继承:

Java 中,抽象类不支持多重继承,一个类只能继承一个抽象类。但是,一个类可以实现多个接口。这意味着如果一个类已经继承了一个抽象类,就无法再继承其他抽象类了,但可以实现多个接口。举例来说,ArrayList 类继承了 AbstractList 抽象类,但同时实现了 List 接口。

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
}

总的来说,接口和抽象类在 Java 中有着不同的使用场景和特性,需要根据具体的需求来选择合适的方式。

接口的多重实现举例

在这里插入图片描述

为什么有抽象类了还要有接口这个概念

在这里插入图片描述

从用户角度看问题:

接口对于用户来说是一个约定或者合约,定义了一组方法的契约,用户可以通过接口来了解一个类提供了哪些功能,而不需要关心具体的实现细节。这种抽象的设计使得用户可以更加专注于如何使用接口提供的功能,而不需要了解背后的具体实现。

强调合约:

接口强调了类与类之间的契约或者约定。通过接口,类之间建立了一种规范化的交流方式,类的设计者向用户承诺了一组特定的行为和功能。这种明确的约定使得不同类之间可以更加灵活地协作,而无需关心具体的实现细节。

强制协作双方无法犯错:

接口强制了类的实现者必须遵循接口定义的契约,提供接口中定义的所有方法的具体实现。这样一来,无论是类的设计者还是类的用户,在使用接口时都可以放心,不会因为接口的实现方式不同而出现错误。接口的存在使得类之间的协作更加可靠,避免了潜在的错误和bug。

通过以上三个角度的解读,可以看出接口在面向对象编程中的重要性。它不仅可以帮助用户更好地理解和使用类的功能,还可以建立类之间的规范化交流方式,提高代码的可靠性和可维护性。


扩展阅读

在这里插入图片描述

面向对象主题链接
类与对象链接
接口与抽象类链接
不可变性链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1501901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

荔枝派zero驱动开发06:GPIO操作(platform框架)

参考&#xff1a; 正点原子Linux第五十四章 platform设备驱动实验 一张图掌握 Linux platform 平台设备驱动框架 上一篇&#xff1a;荔枝派zero驱动开发05&#xff1a;GPIO操作&#xff08;使用GPIO子系统&#xff09; 下一篇&#xff1a;更新中… 概述 platform是一种分层思…

在Leaflet中使用Turf.js生成范围多边形的两种实现方式

目录 前言 一、场景需求 1、Leaflet.js的不足 2、Turf.js 二、原始数据展示 1、点位数据展示 2、定义样式 3、定位数据初始化 三、Turfjs中bbox生成 1、官网讲解 2、轨迹bbox生成 四、Turfjs生成外包多边形 1、官网例子 2、凸多边形生成 总结 前言 在一些共享出…

比特币普通地址、隔离见证(兼容)、隔离见证(原生)、Taproot 地址傻傻分不清楚

我们在使用比特币钱包的时候&#xff0c;可以看到各种地址类型&#xff1a;普通地址、隔离见证&#xff08;兼容&#xff09;、隔离见证&#xff08;原生&#xff09;、Taproot 地址。 看得我们一脸懵逼&#xff0c;为什么会有这么多种类型的地址&#xff1f; 它们之间都有什么…

17、电源管理入门之Power supply子系统

目录 1. Power supply框架都做些什么 2. 相关数据结构和接口 2.1 数据结构 2.2 接口 3. 充电驱动 3.1 Charger Manager 3.2 Fuel Gauge 3.3 Charger IC 4. 怎样基于power supply class编写PSY driver 参考资料: 对于便携设备来说,电源管理更加的重要,因为电池电量…

SaulLM-7B: A pioneering Large Language Model for Law

SaulLM-7B: A pioneering Large Language Model for Law 相关链接&#xff1a;arxiv 关键字&#xff1a;Large Language Model、Legal Domain、SaulLM-7B、Instructional Fine-tuning、Legal Corpora 摘要 本文中&#xff0c;我们介绍了SaulLM-7B&#xff0c;这是为法律领域量…

web组态

演示地址 &#xff1a;by组态[web组态插件] 这是一款可以嵌入到任何项目组态插件&#xff0c;功能全面&#xff0c;可根据自己的项目需要进行二次开发&#xff0c;能大大的节省在组态上的开发时间&#xff0c;代码简单易懂。 一、数据流向图及嵌入原理 数据流向 嵌入原理 …

[N1CTF 2018]eating_cms 不会编程的崽

题倒是不难&#xff0c;但是实在是恶心到了。 上来就是登录框&#xff0c;页面源代码也没什么特别的。寻思抓包看一下&#xff0c;数据包直接返回了sql查询语句。到以为是sql注入的题目&#xff0c;直到我看到了单引号被转义。。。挺抽象&#xff0c;似乎sql语句过滤很严格。又…

读算法的陷阱:超级平台、算法垄断与场景欺骗笔记04_共谋(上)

1. 共谋 1.1. 共谋总比相互竞争要容易得多 1.1.1. 通过共同抬价或稳定价格&#xff0c;企业通常可以赚取更多利润 1.1.2. 依靠人为切割市场&#xff0c;卡特尔组织成员得以在各自的势力范畴内实现垄断 1.2. 一直以来&#xff0c;人类都是价格操纵行为背后的行动者 1.2.1. …

解决方案|珈和科技推出农业特色产业数字化服务平台

今年中央一号文件提出&#xff0c;鼓励各地因地制宜大力发展特色产业&#xff0c;支持打造乡土特色品牌。 然而&#xff0c;农业特色产业的生产、加工和销售仍然面临诸多挑战。产品优质不能优价&#xff0c;优质不能优用的现象屡见不鲜&#xff0c;产业化程度低、生产附加值不…

QtWebEngine模块常用功能

QtWebEngine模块常用功能 https://note.youdao.com/s/Im0k2ZKe 1. 拦截请求 2. 忽略证书错误 3. 下载文件 4. 内嵌谷歌开发者界面 5. 获取Html页面用户选择的文件和目录 6. 获取响应的cookie 所有代码的7z压缩后的Base64编码如下&#xff1a; &#xff08;注意复制出来是…

pytorch的梯度图与autograd.grad和二阶求导

前向与反向 这里我们从 一次计算 开始比如 zf(x,y) 讨论若我们把任意对于tensor的计算都看为函数&#xff08;如将 a*b&#xff08;数值&#xff09; 看为 mul(a,b)&#xff09;&#xff0c;那么都可以将其看为2个过程&#xff1a;forward-前向&#xff0c;backward-反向在pyto…

基于单片机的水平角度仪系统设计

目 录 摘 要 I Abstract II 引 言 1 1控制系统设计 3 1.1系统方案设计 3 1.2系统工作原理 4 2硬件设计 6 2.1单片机 6 2.1.1单片机最小系统 6 2.1.2 STC89C52单片机的性能 7 2.2角度采集电路 8 2.2.1 ADXL345传感器的工作原理 9 2.2.2 ADXL345传感器倾角测量的原理 9 2.2.3 AD…

npm 操作报错记录1- uninstall 卸载失效

npm 操作报错记录1- uninstall 卸载失效 1、问题描述 安装了包 vue/cli-plugin-eslint4.5.0 vue/eslint-config-prettier9.0.0 但是没有使用 -d &#xff0c;所以想重新安装&#xff0c;就使用 uninstall 命令卸载&#xff0c;结果卸载了没反应&#xff0c;也没有报错&#xf…

CubeMX使用教程(5)——定时器PWM输出

本篇我们将利用CubeMX产生频率固定、占空比可调的两路PWM信号输出 例如PA6引脚输出100Hz的PWM&#xff1b;PA7引脚输出500Hz的PWM&#xff0c;双路同时输出 我们还是利用上一章定时器中断的工程进行学习&#xff0c;这样比较方便 首先打开CubeMX对PA6、PA7进行GPIO配置 注&a…

【Web】浅聊Java反序列化之C3P0——JNDI注入利用

目录 简介 原理分析 EXP 前文&#xff1a;【Web】浅聊Java反序列化之C3P0——URLClassLoader利用 【Web】浅聊Java反序列化之C3P0——不出网Hex字节码加载利用 简介 出网的情况下&#xff0c;这个C3P0的Gadget可以和fastjson&#xff0c;Snake YAML , JYAML,Yamlbeans , …

Axure Cloud如何给每个原型配置私有域名

需求 在原型发布之后&#xff0c;自动给原型生成一个独立访问的域名&#xff0c;类似http://u591bi.axshare.bushrose.cn&#xff0c;应该如何配置呢&#xff1f; 准备事项 已备案域名 如何备案&#xff1f;阿里云备案流程 已安装部署Axure Cloud 如何安装部署&#xff0c;请…

【MySQL 系列】MySQL 语句篇_DML 语句

DML&#xff08;Data Manipulation Language&#xff09;&#xff0c;即数据操作语言&#xff0c;用于操作数据库对象中所包含的数据。常用关键字包括&#xff1a;插入&#xff08;INSERT&#xff09;、更新&#xff08;UPDATE&#xff09;、删除&#xff08;DELETE&#xff09…

用 Axios 提升前端异步请求的效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

政安晨:【深度学习处理实践】(三)—— 处理时间序列的数据准备

在深度学习中&#xff0c;对时间序列的处理主要涉及到以下几个方面&#xff1a; 序列建模&#xff1a;深度学习可以用于对时间序列进行建模。常用的模型包括循环神经网络&#xff08;Recurrent Neural Networks, RNN&#xff09;和长短期记忆网络&#xff08;Long Short-Term M…

ubuntu下vscode+STM32CubeMX+openocd+stlinkv2搭建STM32开发调试下载环境

1、换源 清华源 # 默认注释了源码镜像以提高 apt update 速度&#xff0c;如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse # deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restr…