作为一个 javer
当我看到类似这样的代码的时候,我的内心还是有小小的震撼的。
val someday = "today" afterDay 4
当看到这段代码的时候,你有没有懵逼掉?
today
后面没有 .
却是出现了一个 afterDay
这个莫名其妙的东西那我们看看他是怎么实现的了!
在写出上述代码之前我们需要了解一个 Java
中没有的东西,那就是 扩展函数
。
扩展函数的重点就是“扩展”,它扩展的就是某个类的方法、属性等,可以为原本不存在于某个类的方法和属性做扩展。
我们来举 2 个例子,比如对于 String
期望能有一个 join
将字段拼接起来,
val res = "123".append("abc")//结果是123abc
但是 JDK
中的 String
中没有这个 append
方法,同时这个 String
是 JDK 的包,我们也没有很好的办法去修改源码,那么此时扩展函数的作用就来了。
fun String.append(that: String): String {
return this + that
}
上面的就是扩展函数
String.append
表示的就是为 String
这个类扩展 append
这个方法(that:String)
就是一个形参上面的例子很好理解了吧?
对于某个字符串,我们希望他有个 属性
(注意不是方法),比如 a
出现的次数 aTimes
假如 aTimes
是一个方法,可以这么实现
fun String.aTimes(): Int {
return this.toCharArray().filter { it == 'a' }.count()
}
假如 aTimes
是一个 只读属性
,那么如何实现?
val String.aTimes: Int
get() = this.toCharArray().filter { it == 'a' }.count()
val
修饰 只读属性
get()
方法:
后的是获取的类型那么假如某个属性,既是 能读又能写
的,如何实现了?
var StringBuilder.lastChar: Char
get() = get(length - 1)
set(value) {
this.setCharAt(length -1, value)
}
var
修饰:
后的是获取和设置的类型。当我们有了上述基础后,我们就来看看 中缀表达式
的实现。
kotlin
中有一个关键字叫做 infix
,很多翻译叫做 中缀表达式
,我们就先这么称呼着,名字而已,约定俗成。
我们先回顾下文章最先出现的代码:
val someday = "today" afterDay 4
假如 afterDay
是点出来的方法,我们都可以对他进行实现了,比如说
fun String.afterDay(offset: Int): LocalDate {
return when (this) {
"today" -> LocalDate.now().plusDays(offset.toLong())
//省略其他
else -> throw IllegalArgumentException("参数不合法")
}
}
//调用的时候可以
val someDay = "toDay".afterDay(4)
但是我们想要的不是 .
出来的,而是把除 .
和 ()
这些符号去掉,只保留最核心的元素。
其实通过 infix
可以很简答的实现
//中缀表达式:用于两个对象间的运算
infix fun String.afterDay(that: Int): LocalDate {
return when (this) {
"today" -> LocalDate.now().plusDays(that.toLong())
"yesterday" -> LocalDate.now().plusDays(that.toLong() - 1)
"tomorrow" -> LocalDate.now().plusDays(that.toLong() + 1)
else -> LocalDate.now().plusDays(that.toLong())
}
}
//这样调用
val someday = "today" afterDay 4
上述代码中只是加了关键字 infix
,那么就可以不通过 .
来调用方法,而是通过 空格+方法名
的形式调用。
从本质上来说,其实这些都是语法糖,掌握了这些语法糖,当你在可能使用到的地方,确实是有点 甜