扩展属性

例如,给 Float 扩展一个 int 属性:

1
2
3
4
val Float.int
get() = this.toInt()

val test = 13.0f.int

扩展函数

使用

1
2
3
4
5
6
7
8
9
10
package com.xl.test

fun Int.formatString(format: String): String {
return String.format(format, this)
}

printlin(4.formatString("current value = %d"))

//结果
current value = 4
  • 扩展函数属于谁?属于函数左边的类吗?并不是,这里的扩展函数是一个顶层的,它谁也不属于,它只属于它所在的 package。
  • 为什么可以被这个类调用呢?因为我们在这个函数限定了一个 Receiver,也就是函数左边的那个类。

作用域

扩展函数可以写在方法,类,顶层中,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//方法
fun test() {
//...

fun Int.formatString(format: String): String {
return String.format(format, this)
}
}

//类
class Func {
fun Int.formatString(format: String): String {
return String.format(format, this)
}
}

//顶层
package com.xl.test

fun Int.formatString(format: String): String {
return String.format(format, this)
}

扩展函数的引用

普通的成员函数怎么引用:类名::函数名,扩展函数呢?它的类名到底写什么呢?

  • 针对写在顶层的扩展函数,它的类名直接写 Receiver 的类名即可。
  • 针对写在类中等其他扩展函数,它的类名是写坐在类的类名还是写 Receiver 的类名呢?这是有歧义的,所以 Kotlin 不允许我们引用。

跟普通函数的引用一样,扩展函数的引用也可以被调用,直接调用或者用 invoke() 都可以,不过要记得把 Receiver 也就是接收者或者说调用者填成第一个参数:

1
2
3
4
5
6
7
8
9
10
fun String.method(length: Int) {
//nop
}

val temp: String.(Int) -> Unit = String::method

// 3 种调用方式
"test".temp(3)
temp("test", 3)
temp.invole("test", 3)

有无 Receiver 的变量的互换:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
fun String.method1(length: Int) {
println("size = ${this.length}, length = $length")
}

fun method2(text: String, length: Int) {
println("size = ${text.length}, length = $length")
}

// 有 Receiver 的变量 -> 无 Receiver
val a: String.(Int) -> Unit = String::method1
val b: (String, Int) -> Unit = String::method1

// 无 Receiver 的变量 -> 有 Receiver
val c: (String, Int) -> Unit = ::method2
val d: String.(Int) -> Unit = ::method2

"test".a(3)
b("test", 3)

c("test", 3)
"test".d(3)