1. Kotlin 中的 actual 关键字简介
在本教程中,我们将深入讲解 Kotlin 中的 actual
关键字,以及它与 expect
配合使用的典型场景。
2. Kotlin Multiplatform 开发基础
要理解 actual
,首先需要了解 Kotlin Multiplatform Module (KMM) 的基本概念。
KMM 是 Kotlin 提供的一项功能,允许我们用 Kotlin 编写可跨平台运行的代码。这对于移动端开发尤其有用 —— 你可以将 Android 和 iOS 共用的业务逻辑统一管理,减少重复开发。
当然,不同平台总有其特有的 API,比如网络请求、系统时间、UI 渲染等。这些部分仍需在各自平台实现,比如 Android 上使用 Kotlin/Java,iOS 上使用 Swift/Objective-C。
3. 共享模块(Shared Module)的结构
共享模块是 KMM 的核心,它会被 Android 和 iOS 工程分别引用。这个模块本身是纯 Kotlin 编写的,但通过 Kotlin Native 项目 编译成目标平台的原生代码(如 iOS 的 .framework 或 Android 的 .jar)。
尽管共享模块的目标是复用代码,但有些功能仍然需要调用平台 API,比如获取系统时间戳:
✅ 举个例子:
你想在共享模块中获取当前时间戳,但不同平台的系统时间 API 不一样。这时就需要使用 expect
和 actual
来桥接差异。
4. expect 与 actual 的作用
4.1 expect:声明一个需要平台实现的接口
在共享模块中,我们使用 expect
声明一个类或函数的结构,但不提供具体实现:
expect class DateTimeApi() {
fun getCurrentTimestamp(): Long
}
这段代码只是告诉编译器:“这里有一个类,它有一个方法,但具体怎么实现,得看平台”。
4.2 actual:提供平台特定的实现
在 Android 或 iOS 的模块中,我们使用 actual
来提供具体实现。例如,在 Android 上可能是这样:
actual class DateTimeApi actual constructor() {
actual fun getCurrentTimestamp(): Long {
return OffsetDateTime.now().toEpochSecond()
}
}
而在 iOS 上则可能是这样:
actual class DateTimeApi actual constructor() {
actual fun getCurrentTimestamp(): Long {
return NSDate.date().timeIntervalSince1970().toLong()
}
}
⚠️ 注意: actual
必须和 expect
的签名完全匹配,包括类名、方法名、参数类型等。否则编译器会报错。
4.3 编译器如何工作?
Kotlin 编译器会在构建最终的二进制文件时,确保每个 expect
声明都有对应的 actual
实现。如果找不到匹配的实现,编译失败。✅
这确保了共享模块的健壮性和跨平台兼容性。
5. 总结
expect
用于在共享模块中声明一个类、函数或属性,但不提供实现。actual
用于在特定平台模块中提供expect
声明的实际实现。- 二者必须成对出现,且签名一致。
- 使用这套机制可以优雅地实现 Kotlin Multiplatform 下的平台适配逻辑。
📌 示例代码地址:
完整代码可在 GitHub 仓库 找到。
✅ 小贴士:
使用 expect/actual
是 Kotlin Multiplatform 的核心技巧之一,尤其适合处理跨平台差异(如网络、文件、系统时间等)。合理使用可以大幅减少重复代码,提高开发效率。