Kotlin中的标准函数指的是Standard.kt文件中定义的函数,任何Kotlin代码都可以自由调用所有的标准函数。
之前提到let函数,该函数主要作用是配合?.操作符进行辅助判空处理的。
这里再看几个标准函数with/run/apply。
with函数接收两个参数,第一个参数可以是一个任意类型的对象,第二个参数是一个Lambda表达式。with函数会在Lambda表达式中提供第一个参数对象的上席文,并使用Lambda表达式中的最后一行代码作为返回值返回。
其形式类似于:
- val result = with(obj) {
- // obj context
- "value"
- }
该函数可以在连续调用同一个对象的多个方法时让代码变得更加简洁。
- val list = listOf("apple", "orange", "banana")
- val builder = StringBuilder()
- builder.append("Start eating fruits.\n")
- for (fruit in list) {
- builder.append(fruit).append("\n")
- }
- builder.append("Ate al fruits.")
- val result = builder.toString()
- println(result)
上面的代码逻辑很简单,只是将各个字符串进行打印,其结果为:
- Start eating fruits.
- apple
- orange
- banana
- Ate al fruits.
但是上面代码多次调用了builder对象的方法,而如果使用with函数,则有:
- val list = listOf("apple", "orange", "banana")
- val result = with(StringBuilder()) {
- append("Start eating fruits.\n")
- for (fruit in list) {
- append(fruit).append("\n")
- }
- append("Ate all fruits")
- toString()
- }
- println(result)
上面的代码首先给with函数的第一个参数传入了一个StringBuilder对象,之后的Lambda表示式的上下文就是该StringBuilder对象,因此便可以直接使用append之类的方法调用,然后最后一行代码的执行结果会返回。
run函数通常不会直接调用,而是要在某个对象的基础上调用,并且run函数只接收一个Lambda参数,并且会在Lambda表达式中提供调用对象的上下文。其它方面和with函数类似,也会将Lambda表示式的最后一行代码作为返回值返回。
- val result = obj.run {
- // obj context
- "value"
- }
而如果使用run函数对上述代码改写,则为:
- val list = listOf("apple", "orange", "banana")
- val result = StringBuilder().run {
- append("Start eating fruits.\n")
- for (fruit in list) {
- append(fruit).append("\n")
- }
- append("Ate all fruits")
- toString()
- }
- println(result)
代码上的变动很小,不过能够实现一样的功能。
apply函数和run函数也类似,都要在某个对象上调用,并且只接收一个Lambda参数,也会在Lambda表达式中提供调用对象的上下文,但是apply函数无法指定返回值,而是会自动返回调用对象本身。
- val result = obj.apply {
- // obj context
- }
使用apply实现上面的代码,则为:
- val list = listOf("apple", "orange", "banana")
- val result = StringBuilder().run {
- append("Start eating fruits.\n")
- for (fruit in list) {
- append(fruit).append("\n")
- }
- append("Ate all fruits")
- }
- println(result.toString())
代码变动仍然很小,不过由于apply没有返回值,只能通过调用StringBuilder的toString方法进行打印。
静态方法指不需要创建实例就能够调用的方法。
静态方法很适合编写一些工具类的功能,因为功能类通常没有创建实例的必要,是全局通用的。
虽然其它编程语言中,定义一个静态方法很简单,但是Kotlin却弱化了这方面的使用。
如果需要使用类似的功能,单例类就可以实现。不过单例类会将整个类中方法的调用方式都变为类似于静态方法的调用方式。而如果只希望类中的某一个方法变为静态方法的调用方式,就需要使用到之前提到的companion object了。
- class Util {
- fun doAction1() {
- println("doAction1")
- }
-
- companion object {
- fun doAction2() {
- println("doAction2")
- }
- }
- }
-
- fun main() {
- Util().doAction1()
- Util.doAction2()
- }
上面的doAction1是普通方法,需要创建Util类的实例才可调用,而doAction2方法则可以通过静态方法的调用方式进行调用。
但其实doAction2方法并不是静态方法,companion object实际上会在Util类的内部创建一个伴生类,而doAction2方法就是定义在该伴生类中的实例方法。只是Kotlin会保证Util类始终只会存在一个伴生类对象,因此调用Util.doAction2方法实际上就是调用了Util类中伴生类对象的doAction2方法。
上面只是静态方法类似的调用形式和使用方法,如果需要定义真正的静态方法,Kotlin提供了两种实现方式:
将单例类或companion object中的方法加上@JvmStatic注解,Kotlin就会将对应方法编译为真正的静态方法。
- class Util {
- fun doAction1() {
- println("doAction1")
- }
-
- companion object {
- @JvmStatic
- fun doAction2() {
- println("doAction2")
- }
- }
- }
但是@JvmStatic注解只能加在单例类或companion object中的方法上,不能加在普通方法上。
顶层方法指没有定义在任何类中的方法。
Kotlin编译器会将所有的顶层方法全部编译为静态方法,比如main方法。
而所有顶层方法可以在任何位置被直接调用,而不用考虑包路径,也不用创建实例,直接调用即可。比如main方法,可以在任意位置直接调用。