本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点
KMP使用expect
和 actual
关键字
在 Kotlin Multiplatform 项目中,expect
和 actual
关键字被用于处理不同平台的 API 调用。以下是如何使用这些关键字的详细步骤和规则:
1、 定义预期声明(Expected Declarations):
在共通代码集中(例如 commonMain
),使用 expect
关键字声明一个结构,这可以是函数、属性、类、接口、枚举或注解。这些预期声明不包含实现代码,而是作为平台无关的 API 供共通代码使用。
2、 提供实际声明(Actual Declarations):
在每个平台特定的源代码集中(例如 androidMain
、iosMain
),声明与预期声明相同的结构,并使用 actual
关键字标记。这些实际声明通常包含使用特定平台库的实现。
3、 编译器匹配:
编译特定目标平台时,编译器会尝试匹配共通代码集中的每个 expect
声明与平台特定源代码集中的相应 actual
声明。编译器确保:
- 每个
expect
声明在每个平台特定源代码集中都有匹配的actual
声明。 expect
声明不包含实现。- 每个
actual
声明与对应的expect
声明使用相同的包名。
4、 使用依赖注入(Dependency Injection, DI):
在采用 DI 框架的项目中,可以在共通代码中使用 expect
声明接口,然后通过 DI 框架配置,为不同平台注入 actual
实现。这种方式适用于管理平台特定的依赖。
5、 处理枚举类:
当使用 expect
关键字声明枚举类时,每个平台模块应该提供一个 actual
声明,包含相同的枚举值常数,也可以包含额外的枚举值常数。这允许在共通代码中声明枚举,而在平台特定代码中扩展它。
6、 类型别名:
如果需要使用特定平台的现有类型实现预期声明,可以使用类型别名(typealias)来连接预期声明和平台特定的类型。这在无法直接向平台类型添加 actual
关键字时非常有用。
7、 扩展可见性: 实际实现的可见度可以超过对应的预期声明。这在不希望将 API 公开给所有用户时非常有用。从 Kotlin 2.0 开始,编译器不再限制可见性的变化。
通过这种方式,Kotlin Multiplatform 允许开发者编写可在多个平台上运行的共享代码,同时保留对每个平台特定 API 的访问能力,实现代码的最大化重用和原生性能的结合。
代码示例
以下是一个使用 expect
和 actual
关键字在 Kotlin Multiplatform 项目中处理不同平台 API 调用的代码示例:
共通代码 (commonMain):
// 预期声明:在共通代码中声明一个函数,但不提供实现。
expect fun getPlatformName(): String
expect class PlatformSpecificClass {
fun doSomething(): String
}
Android 平台代码 (androidMain):
// 实际声明:为 Android 平台提供 getPlatformName() 函数的具体实现。
actual fun getPlatformName(): String = "Android"
// 实际声明:为 Android 平台提供 PlatformSpecificClass 类的具体实现。
actual class PlatformSpecificClass actual constructor() {
actual fun doSomething(): String = "Doing something on Android"
}
iOS 平台代码 (iosMain):
// 实际声明:为 iOS 平台提供 getPlatformName() 函数的具体实现。
actual fun getPlatformName(): String = "iOS"
// 实际声明:为 iOS 平台提供 PlatformSpecificClass 类的具体实现。
actual class PlatformSpecificClass actual constructor() {
actual fun doSomething(): String = "Doing something on iOS"
}
在这个示例中,我们定义了两个预期声明:一个函数 getPlatformName()
和一个类 PlatformSpecificClass
。这些预期声明在共通代码中声明,但它们的实现被留给了特定平台的代码。
对于每个平台,我们提供了相应的实际声明。例如,getPlatformName()
函数在 Android 上返回字符串 "Android",而在 iOS 上返回 "iOS"。同样,PlatformSpecificClass
类在两个平台上有不同的实现,但它们都有一个 doSomething()
方法,该方法返回一个特定于平台的字符串。
这样,当您在共通代码中调用 getPlatformName()
或创建 PlatformSpecificClass
的实例时,Kotlin 编译器会自动选择并使用适当平台的实际实现。这使得您可以在不同的平台上重用共通逻辑,同时保持对平台特定功能的访问。
欢迎关注我的公众号AntDream查看更多精彩文章!