本篇博客主要讲解Kotlin语言中infix函数的运用
什么是 infix 函数
Kotlin允许在不使用括号和点号的情况下调用函数,那么这种函数被称为 infix 函数。
系统 infix 函数示例
系统方法
1
2
3
4
5
6
7*
* Creates a tuple of type [Pair] from this and [that].
*
* This can be useful for creating [Map] literals with less noise, for example:
* samples.collections.Maps.Instantiation.mapFromPairs
*/
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)相关示例
1
2
3
4
5map(
1 to "one",
2 to "two",
3 to "three"
)
除了用于创建Pair <A,B>实例的to()函数之外,还有一些其他函数定义为中缀。
例如,各种数字类Byte,Short,Int和Long都定义了按位函数and()或or(),shl(),shr(),ushr()和xor(),从而允许更多可读的表达式:
1 | val color = 0x123456 |
编写自定义 infix 函数
通常,我们将要编写自己的infix方法。例如,当为我们的应用程序编写领域特定语言时,这些功能尤其有用,从而使DSL代码更具可读性。
一些Kotlin库已经使用此方法产生了很大的效果。
例如,mockito-kotlin库定义了一些infix函数-doAnswer,doReturn和doThrow-在定义模拟行为时使用。
创建infix 函数需要满足以下要求:
- 它们必须是成员函数或扩展函数;
- 它们必须只有一个参数;
- 其参数不得接受可变数量的参数且不能有默认值。
请注意:中缀函数总是要求指定接收者与参数。当使用中缀表示法在当前接收者上调用方法时,需要显式使用 this;不能像常规方法调用那样省略。
1 | class MyStringCollection { |
示例如下:
1 | class Assertion<T>(private val target: T) { |
- 这看起来很简单,而且与其他Kotlin代码没有什么不同。但是,infix关键字的存在使我们可以编写如下代码:这是更清晰易读和易于理解的。
1
2
3
4val result = Assertion(5)
result isEqualTo 5 // This passes
result isEqualTo 6 // This fails the assertion
result isDifferentFrom 5 // This also fails the assertion
注意,也可以将infix函数编写为现有类的扩展方法。
这可能很强大,因为它使我们能够从其他地方(包括标准库)扩充现有的类,以满足我们的需求。
例如,让我们在字符串中添加一个函数,以拉出与给定正则表达式匹配的所有子字符串:
1 | infix fun String.substringMatches(r: Regex) : List<String> { |
其他
中缀函数与操作符的优先级
- 中缀函数调用的优先级低于算术操作符、类型转换以及 rangeTo 操作符
1
2
31 shl 2 + 3 等价于 1 shl (2 + 3)
0 until n * 2 等价于 0 until (n * 2)
xs union ys as Set<*> 等价于 xs union (ys as Set<*>) - 中缀函数调用的优先级高于布尔操作符 && 与 ||、is- 与 in- 检测以及其他一些操作符。
1
2a && b xor c 等价于 a && (b xor c)
a xor b in c 等价于 (a xor b) in c