Kotlin 中的 infix 关键字(中缀函数)

在 Kotlin 中,infix 是一个关键字,用于定义中缀函数(Infix Functions)。

中缀函数允许我们在调用函数的时候使用更加简洁的中缀符号(通常是一个操作符),而不是传统的点符号调用方式。中缀函数的作用是使代码更具可读性,特别是在编写某些领域特定语言(DSL)时非常有用。

在 mapOf 函数中允许我们用 A to B 这样的语法来构建键值对,它的具体实现是怎样的呢?以下是 to 函数的源码:

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

可以看出,这里使用定义泛型函数的方式将 to 函数定义到了 A 类型下,并且接收一个 B 类型的参数。因此 A 和 B 可以是两种不同类型的泛型,也就使得我们可以构建出字符串 to 整型这样的键值对。

再来看 to 函数的具体实现,非常简单,就是创建并返回一个 Pair 对象。也就是说, A to B 这样的语法结构实际上得到是一个包含 A、B 数据的 Pair 对象,而 mapOf 函数实际上接收的正式一个 Pair 类型的可变参数列表,这样我们就将这种神奇的语法结构完全解密了。

下面,我们模仿 to 函数的源码来编写一个自己的键值对构建函数,在 infix.kt 文件中添加如下代码:

infix fun <A, B> A.with(that: B): Pair<A, B> = Pair(this, that)

这里只是将 to 函数改名为 with 函数,其他的实现逻辑是相同的,因为相信没有什么解释的必要。现在我们的项目中就可以使用 with 函数来构建键值对了,还可以将构建的键值对传入 mapOf 方法中:

val map = mapOf("Apple" with 1, "Banana" with 2, "Orange" with 3, "Pear" with 4, "Grape" with 5
)

这就是 infix 函数(中缀函数),灵活运用它可以让语法变得更具可读性。

一个中缀函数的表达形式非常简单:

A 中缀方法 B

当我们要定义一个中缀函数的时候,它必须满足如下条件:

  • 该中缀函数必须是某个类型的扩展函数或者成员方法;
  • 该中缀函数只能有一个参数;
  • 虽然 Kotlin 的函数参数支持默认值,但中缀函数的参数不能有默认值,否则以上形式的 B 会缺失,从而对中缀表达式的语义造成破坏;

再比如,String 类中有一个 startWith 函数,用于判断一个字符串是否是以某个指定的参数开头的。比如下面这段代码的判断结果就是 true:

if ("Hello Kotlin".startsWith("Hello")){// 处理具体的逻辑
}

startWith 函数的用法虽然非常简单,但是借助 infix 函数,我们可以使用一种更具可读性的语法来表达这段代码。新建一个 infix.kt 文件:

infix fun String.beginsWith(prefix: String) = startsWith(prefix)

首先,去掉前面的 infix 关键字不谈,这就是一个 String 类的扩展函数。我们给 String 类添加了一个 beginsWith 函数,它也是用于判断一个字符串是否是以某个指定参数开头的,并且它的内部实现就是调用 String.startsWith 函数。

但是加了 infix 关键字之后,beginsWith 函数就变成了 infix 函数,这样除了传统的函数调用方法外,我们还可以用一种特殊的语法糖格式调用 beginsWith 函数,如下所示:

if ("Hello World" beginsWith("Hello")) { // 注意没有 .// 处理具体的逻辑
}

从这个例子中就能看出,infix 函数的语法规则并不复杂,上述的代码其实调用的 “Hello Kotlin” 这个字符的 beginsWith 函数,并传入 “Hello” 字符串作为参数。但是 infix 函数允许我们将函数调用的小数点、括号等计算机相关的语法去掉,从而使用一种更接近英语的语法来编写程序,使得代码看起来更具有可读性。

下面看一些复杂的例子。比如说这里有个集合,如果想要判断集合中是否包括某个指定元素,一般可以这样写:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
if (list.contains("Banana")) {// 处理具体的逻辑
}

我们仍然可以借助 infix 函数让这段代码变得更具可读性,在 infix.kt 文件中添加如下代码:

infix fun <T> Collection<T>.has(element: T) = contains(element)

可以看到,我们给 Collection 接口添加了一个扩展函数,这是因为 Collection 是 Java 以及 Kotlin 所有集合的总接口。因此给 Collection 添加了一个 has 函数,那么,所有集合的子类就都可以使用这个函数了。

另外,这里还用了泛型函数的定义方法,从而使得 has 函数可以接收任意类型具体类型的参数。而这个函数内部的实现就是调用了 Collection 接口中的 contians() 函数而已。也就是说,has 函数和 contains 函数的功能世纪上是一摸一样的,只是它多了一个 infix 关键字,从而拥有了 infix 函数的语法糖功能。

现在我们就可以使用如下的语法来判断集合中是否包括某个指定的元素:

val list = listOf("Apple", "Banana", "Orange", "Pear", "Grape")
if (list has "Banana") {// 处理具体的逻辑
}

将 infix.kt 反编译成 Java 代码:

public final class InfixKt {public static final boolean beginsWith(@NotNull String $this$beginsWith, @NotNull String prefix) {Intrinsics.checkNotNullParameter($this$beginsWith, "$this$beginsWith");Intrinsics.checkNotNullParameter(prefix, "prefix");return StringsKt.startsWith$default($this$beginsWith, prefix, false, 2, (Object)null);}public static final boolean has(@NotNull Collection $this$has, Object element) {Intrinsics.checkNotNullParameter($this$has, "$this$has");return $this$has.contains(element);}@NotNullpublic static final Pair with(Object $this$with, Object that) {return new Pair($this$with, that);}
}

可以看到都是普通的函数调用,也就是说中缀函数的原理是编译器在语法层面给予了支持。Kotlin 的很多特性都是在语法和编译器上的优化。

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

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

相关文章

Linux_应用篇(24) CAN 应用编程基础

本章我们学习 CAN 应用编程&#xff0c; CAN 是目前应用非常广泛的现场总线之一&#xff0c;主要应用于汽车电子和工业领域&#xff0c;尤其是汽车领域&#xff0c;汽车上大量的传感器与模块都是通过 CAN 总线连接起来的。 CAN 总线目前是自动化领域发展的热点技术之一&#xf…

2024软件测试面试题大全【含答案】

一、面试基础题 简述测试流程&#xff1a; 1、阅读相关技术文档&#xff08;如产品PRD、UI设计、产品流程图等&#xff09;。 2、参加需求评审会议。 3、根据最终确定的需求文档编写测试计划。 4、编写测试用例&#xff08;等价类划分法、边界值分析法等&#xff09;。 5…

ntp自动同步时间 ubuntu入门之二十四

当我们的电脑的CMOS电池失效时&#xff0c;我们可以在登陆shell之后通过脚本自动同步ntp时间。 Debian 11系统脚本编写如下&#xff1a; $ pwd /home/user$ ls Desktop Documents Downloads Music Pictures Public Templates Videos debian initrd mnt sync-time…

活动|华院计算受邀参加2024全球人工智能技术大会(GAITC),探讨法律大模型如何赋能社会治理

6月22至23日&#xff0c;备受瞩目的2024全球人工智能技术大会&#xff08;GAITC&#xff09;在杭州市余杭区未来科技城隆重举行。本届大会以“交叉、融合、相生、共赢”为主题&#xff0c;集“会、展、赛”为一体&#xff0c;聚“产、学、研”于一堂。值得一提的是&#xff0c;…

夏天喝酱香酒的好处有哪些?

夏天适合喝酱香酒的原因主要有促进新陈代谢、祛湿气、保护心脏等。下面酱酒亮哥将详细分析夏天适合喝酱香酒的具体原因&#xff1a; 促进新陈代谢 增加血液循环&#xff1a;夏天天气炎热&#xff0c;人体的新陈代谢本来就比冬季要旺盛&#xff0c;而酱香型白酒含有较多的酒精…

Batch 入门学习

Batch 入门学习 Batch 是一种在计算机科学和数据处理领域中广泛使用的技术&#xff0c;用于批量处理数据和任务。本文将带你深入了解 Batch 的基本概念、应用场景、工作原理和一些常用工具&#xff0c;帮助你快速入门 Batch 处理技术。 目录 Batch 概述Batch 处理的应用场景…

深度解析RocketMq源码-消费者索引ConsumeQueue

1.绪论 rocketmq的broker中关于消息持久化的组件主要包含三个&#xff0c;分别是&#xff1a;持久化消息到文件中的组件commitLog&#xff1b;根据消息key索引commitLog日志的indexFile&#xff1b;消费者根据topic和queueId查询commitLog日志的consumeQueue。前面已经介绍com…

使用QGIS进行研究区域制图实战

目录 前言 一、QGIS的版本和数据介绍 1、关于QGIS版本 2、需要准备的数据 二、准备制图 1、制作全国区位图 2、矢量和遥感信息的编辑 三、出图编辑 1、设置主题信息 2、打印布局制作 3、美化地图 总结 前言 俗话说“一图胜千言”&#xff0c;在地理信息的领域中&…

Feign:简化微服务通信的利器

介绍 1.1 什么是 Feign&#xff1f; Feign 是一个声明式、模板化的 HTTP 客户端&#xff0c;它简化了编写 Web 服务客户端的过程。它的主要目的是使 HTTP API 客户端的开发变得更加简单和直观。Feign 的设计理念是将 HTTP 客户端的细节隐藏在背后&#xff0c;使开发者可以专注…

ai智能语音机器人在电销里发挥怎样的作用

得益于语音识别技术的的进步&#xff0c;人工智能发展越来越成熟。相信作为企业的管理者&#xff0c;都遇到过这样的事&#xff1a;一个电销新人刚刚入行&#xff0c;需求经过一两个月的学习培训才能成为一名合格的销售人员。在这段学习的期间&#xff0c;企业投入的成本是没有…

使用 Selenium 获取 Web 页面信息的全指南

目录 为什么使用 Selenium 获取页面信息Selenium 基础设置获取页面标题获取当前 URL获取页面源代码获取元素的文本获取元素的属性获取 Cookie截图示例代码总结 正文 1. 为什么使用 Selenium 获取页面信息 在 Web 自动化测试和数据抓取中&#xff0c;获取页面信息是一个基本…

来聊聊nacos

先关注下下方公众号呗&#xff1a; 第1部分&#xff1a;引言 微服务的挑战 尽管微服务架构带来了许多好处&#xff0c;如敏捷性、可扩展性和容错性&#xff0c;但它也带来了一些挑战&#xff0c;特别是在服务发现、配置管理、服务间通信和运维管理方面。这些挑战需要有效的解…

opencv 图像的缩放(放大,缩小),翻转与旋转

目录 opencv 图像的缩放(放大&#xff0c;缩小)&#xff0c;翻转&#xff0c;旋转1、图像的缩放&#xff0c;旋转过程中为什么需要插值&#xff1a;2、常见的插值算法包括&#xff1a;3、图像的缩放&#xff0c;翻转&#xff0c;旋转&#xff1a;&#xff08;1&#xff09;图像…

混凝土搅拌站中的智能化系统应用

随着科技的飞速发展&#xff0c;混凝土搅拌站已经进入了现代化、智能化的新时代。现代自动化、智能化技术的应用&#xff0c;使得混凝土搅拌站更加高效、准确、可靠&#xff0c;同时也提高了生产效率和质量。本文将带你深入探索混凝土搅拌站中运用到现代自动化、智能化的方方面…

Java代码基础算法练习-删除有序数组中的重复项-2024.05.07

任务描述&#xff1a; 有一批同学需要计算各自的出生年月是否闰年。请使用算法计算出他们的出生年份是否闰年。 解决思路&#xff1a; 如果要一次性输出结果&#xff0c;就是先输入数字n&#xff0c;确定首先循环几次&#xff0c;在每次循环中进行闰年判断操作&#xff0c;每次…

国外的Claude3.5 Sonnet Artifacts和国内的CodeFlying孰强孰弱?

在Claude 3.5 Sonnet发布后&#xff0c;最受大家关注的问题应该就是它在编写代码能力上的变化。 要知道在Claude3.0发布以来的这几个月就因为它的编写代码能力而一直受到人们的诟病。 那Anthropic这次终于是不负众望&#xff0c;在Claude 3.5 Sonnet中更新了一个叫做Artifact…

【STM32】SysTick系统滴答定时器

1.SysTick简介 CM4内核的处理和CM3一样&#xff0c;内部都包含了一个SysTick定时器&#xff0c;SysTick 是一个24 位的倒计数定时器&#xff0c;当计到0 时 &#xff0c;将 从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除&#xf…

使用阿里云效API操作流水线

使用阿里云效&#xff08;Alibaba Cloud DevOps&#xff09;API操作流水线时&#xff0c;需要注意以下几个方面&#xff1a; 认证与授权 确保你已经获取了正确的访问凭证&#xff08;AccessKey ID 和 AccessKey Secret&#xff09;&#xff0c;并且这些凭证具有足够的权限来执行…

优维“统一开放平台”:开放、开发、集成、客制化

基于丰富完善的产品体系&#xff0c;优维重磅推出了统一开放平台。这款由优维自主设计与研发&#xff0c;集数据开发、能力开放、能力集成、客制化为一体的统一开放平台&#xff0c;具备应用市场、应用开发、连接能力、采控平台、API集市、开发者工具等功能模块&#xff0c;可为…

探索MySQL的执行奥秘:从查询执行到数据存储与优化的深入解析

MySQL是一个功能强大且广泛应用的关系数据库管理系统。理解MySQL的执行机制、优化策略以及数据存储方式&#xff0c;对于数据库开发和管理至关重要。本文将详细解析这些内容&#xff0c;通过具体实例和实用建议&#xff0c;帮助读者深入掌握MySQL的高级特性。 一、MySQL的执行…