infix
函数是什么难理解的事物,它只是把编程语言函数调用的语法规则调整了一下而已,比如A to B
这样的写法,实际上等价于A.to(B)
的写法。
在String类中,有一个startsWith()函数,它可以用于判断一个字符串中是否以某一个字符开头的,例如以下代码:
if ("test".startsWith("te")){
}
这个代码一定返回为true的。startsWith()
函数的用法虽然非常简单,但是借助infix
函数,我们可以使用一种更具可读性的语法来表达这段代码。新建一个infix.kt文件,然后编写如下代码:
infix fun String.beginsWith(testFix: String) = startsWith(testFix)
首先,除去最前面的infix
关键字不谈,这是一个String
类的扩展函数。我们给String
类添加了一个beginsWith()
函数,它也是用于判断一个字符串是否是以某个指定参数开头的,并且它的内部实现就是调用的String
类的startsWith()
函数。
但是加上了infix
关键字之后,beginsWith()
函数就变成了一个infix
函数,这样除了传统的函数调用方式之外,我们还可以用一种特殊的语法糖格式调用beginsWith()
函数,如下所示:
if ("test" beginsWith "te"){
}
另外,infix
函数由于其语法糖格式的特殊性,有两个比较严格的限制:首先,infix
函数是不能定义成顶层函数的,它必须是某个类的成员函数,可以使用扩展函数的方式将它定义到某个类当中;其次,infix
函数必须接收且只能接收一个参数,至于参数类型是没有限制的。只有同时满足这两点,infix
函数的语法糖才具备使用的条件。
在集合中,判断集合是否包含某个指定元素的时候,一般会用到contains函数:
val infixList = listOf(1,2,3,4,5,6,7)
if (infixList.contains(1)){
}
那我们应该怎么样定义一个infix函数来使其更具有可读性呢?代码如下:
infix fun <T> Collection<T>.has(element: T) = contains(element)
那么我们就可以这样调用了:
if (infixList has 1){
}
这就是infix
函数给我们带来的诸多有意思的功能,灵活运用它确实可以让语法变得更具可读性。