10-特定平台声明
2.3.3 特定平台声明
Kotlin多平台项目的一个关键功能是通用代码依赖于特定平台的声明方式。在其他语言中,可以通过在通用代码中构建一组接口,并在平台特定的模块中实现这些接口来实现。然而,对于Kotlin这种跨平台项目来说,这种方法并不理想。为了达到多平台代码复用的目的,Kotlin提供了一种预期和实际的声明机制。通过这种机制,通用模块可以定义一个预期的声明,然后在平台模块根据提供的预期声明来实现实际声明。
具体使用时,可以通过expected以及actual方式来声明通用代码与平台特定部分的依赖关系,其中,expected用于声明一个指定的API(类、接口、注释、顶层声明等),actual用于声明与API相关的平台实现或是用于实现在外部库中对API的现有别名引用。下面是官方提供的一个关于多平台项目实现的例子。
//通用模块
expect class Foo(bar: String) {
fun frob()
}
fun main(args: Array<String>) {
Foo("Hello").frob()
}
相应的JVM平台模块的实现如下。
//JVM特定模块
actual class Foo actual constructor(val bar: String) {
actual fun frob() {
println("Frobbing the $bar")
}
}
学习Kotlin的多平台特性时应注意以下几点。
- 通用模块中的预期声明及其平台实现使用完全相同的限定名称。
- 预期声明使用expect关键字标记,实际声明使用actual关键字标记。
- 预期声明不包含任何实现代码。
预期声明不仅限于接口和接口成员,还可以使用expect修饰符修饰其他声明,包括顶级声明和注释等。如果有一个特定平台库,现在希望在通用代码中使用这个库并为另一个平台提供自己的实现,则可以使用typealias来修饰实际声明。代码示例如下。
expect class AtomicRef<V>(value: V) {
fun get(): V
fun set(value: V)
fun getAndSet(value: V): V
fun compareAndSet(expect: V, update: V): Boolean
}
actual typealias AtomicRef<V> = java.util.concurrent.atomic.AtomicReference<V>
如果需要为项目编写测试程序,以便在每个平台项目中进行编译和运行,可以使用Kotlin提供的测试库。其中,kotlin-test-annotations-common库作用于通用模块,kotlin-test-junit库作用于JVM模块,kotlin-test-js库则作用于JavaScript模块。