Kotlin学习 7 -- infix函数

本篇文章主要介绍以下几个知识点:

  • 使用 infix 函数构建更可读的语法
    内容参考自第一行代码第3版
SUMMER DAY (图片来源于网络)

在前面的学习中,使用过 A to B 这样的语法结构构建键值对。这种语法结构可读性高,更接近于用英语的语法来编写程序。

上面的 to 并不是 Kotlin 语言中的关键字,之所以能使用 A to B 这样是因为 Kotlin 提供了一种高级语法糖特性:infix 函数

infix 函数只是把编程语言函数调用的语法规则调整了一下而已,如 A to B 其实等价于 A.to(B)的写法。

举个栗子,String 类中的 startsWith() 函数:

if("Hello Wonderful".startsWith("Hello")) {
    // to do something
}

上面startsWith() 函数的用法简单,若借助 infix 函数则可以用一种更具可读性的语法来表达。

在创建 String 类的扩展函数 beginsWith() 的前面加上关键字 infix 如下:

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

这样 beginsWith() 函数就变成了一个 infix 函数,调用方式如下:

if ("Hello Wonderful" beginsWith "Hello"){
    // to do something
}

另外,infix 函数有两个较严格的限制:

  • infix 函数是不能定义成顶层函数的,它必须是某个类的成员函数,可以用扩展函数的方式将它定义到某个类中。

  • infix 函数必须接收且只能接收一个参数,参数类型不限制。


下面举个稍微复杂的栗子,比如一个集合:

val list = listOf("apple", "orange", "pear")
if (list.contains("orange")) {
    // to do something
}

借助 infix 函数并给 Collection 接口添加一个扩展函数 has() 如下:

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

这样就可以用如下语法来判断集合中是否包括某个指定的元素:

val list = listOf("apple", "orange", "pear")
if (list has "orange") {
    // to do something
}

接下来思考下 mapOf() 函数中允许使用 A to B 的语法结构来构建键值对,是如何实现的呢?

直接看下 to() 的源码如下:

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

可以看到,用定义泛型函数的方式将 to() 函数定义到了 A 类型下,并接收一个 B 类型参数,创建并返回一个 Pair 对象。

也就是说 A to B 实际上得到的是一个包含 A、B 数据的 Pair 对象,而 mapOf() 函数接收的正是一个 Pair 类型的可变参数列表。

当然,也可以模仿 to() 函数的源码来编写一个自己的键值对构建函数:

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

with() 函数构建的键值对传入 mapOf() 方法中:

val map = mapOf("name" with "wonderful", "age" with 18)

本篇文章就介绍到这。

你可能感兴趣的:(Kotlin学习 7 -- infix函数)