大多数时候我们在顶层定义扩展,即直接在包里:
这样我们就可以在整个包里使用这些扩展。
要使用其他包的扩展,我们需要在调用方导入它:
import foo.bar.goo // 导入所有名为“goo”的扩展
// 或者
import foo.bar.* // 从“foo.bar”导入一切
fun usage(baz: Baz) {
baz.goo()
}
声明一个扩展函数,我们需要用被扩展的类型来作为前缀。
比如说,我们不喜欢类似下面的双重否定式的逻辑判断(绕脑子):
>>> !"123".isEmpty()
下面代码为 MutableList<Int>
添加一个swap
函数:
val tmp = this[index1] // this对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
这个 this
关键字在扩展函数内部对应到接收者对象(传过来的在点.
符号前的对象)
现在,我们对任意 MutableList<Int>
调用该函数了。
当然,这个函数对任何 MutableList<T>
起作用,我们可以泛化它:
fun <T> MutableList<T>.mswap(index1: Int, index2: Int) {
val tmp = this[index1] // “this”对应该列表
this[index1] = this[index2]
this[index2] = tmp
}
为了在接收者类型表达式中使用泛型,我们要在函数名前声明泛型参数。
完整代码示例
package com.easy.kotlin
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
@RunWith(JUnit4::class)
class ExtensionsDemoTest {
@Test fun testExtensionsDemo() {
val demo = ExtensionsDemo()
demo.useExtensions()
}
}
扩展不是真正的修改他们所扩展的类。我们定义一个扩展,其实并没有在一个类中插入新函数,仅仅是通过该类型的变量,用点.
表达式去调用这个新函数。
扩展属性
和函数类似,Kotlin 支持扩展属性:
val <T> List<T>.lastIndex: Int
get() = size - 1
注意:由于扩展没有实际的将成员插入类中,因此对扩展的属性来说,它的行为只能由显式提供的 getters/setters 定义。
代码示例:
我们可以直接使用包中扩展的属性lastIndex
: