在 Kotlin Multiplatform 中,我可以有一个“expect”类型,在一个平台上是简单类型,在另一个平台上是参数化类型吗?

In Kotlin Multiplatform can I have an 'expect' type that is a simple type on one platform and a parameterized type on another?

提问人:hippietrail 提问时间:5/4/2023 更新时间:5/5/2023 访问量:312

问:

从概念上讲,我想这样做:

// Expect file (commonMain)
expect class PlatformDir
    
// Platform-specific implementation for JVM
actual typealias PlatformDir = File
    
// Platform-specific implementation for Linux/macOS
actual typealias PlatformDir = CPointer<DIR>

接受简单的 JVM 类型,但不接受 Linux/macOS 的参数化类型:

预期类“PlatformDir”在模块中没有实际声明 对于本机,以下声明是 不兼容,因为类型参数的数量不同: public 实际类型别名 PlatformDir = CPointer

实际类型别名右侧的类型参数应为 其类型参数按相同顺序排列,例如 'actual typealias Foo<A, B> = Bar<A, B>'

实际类型别名“PlatformDir”没有相应的预期值 declaration 以下声明不兼容,因为 number 的类型参数不同: public final expect 类 PlatformDir

首先将参数化类型移动到其自己的 typealias 中也不起作用:

private typealias CPointer_DIR = CPointer<DIR>
actual typealias PlatformDir = CPointer_DIR

它仍然抱怨类型参数的数量错误,并有这个额外的错误:

实际类型别名的右侧应该是一个类,而不是其他类型别名

我是 Kotlin 和 JVM 以及 Kotlin Multiplatform 的菜鸟,所以我觉得这一定是可能的,而无需将两者都包装在一个类中。 谷歌搜索我找不到任何人讨论这个问题,AI 聊天机器人似乎只是抓住了越来越复杂并且也没有构建的稻草。

Kotlin Kotlin-多平台 类型别名

评论


答:

3赞 user11853725 5/5/2023 #1

您正在尝试对 JVM 使用简单类型,对本机平台使用参数化类型,但不幸的是,Kotlin 不支持在预期和实际声明中使用不同数量的类型参数。

但是,您可以通过稍微不同的方法实现所需的结果,在期望声明中使用泛型类,然后提供实际实现。下面是一个示例:

// Expect file (commonMain)
expect class PlatformDir<T>

// Platform-specific implementation for JVM
actual typealias PlatformDir<T> = File

// Platform-specific implementation for Linux/macOS
actual typealias PlatformDir<T> = CPointer<DIR>

在本例中,你在 expect 声明中使用泛型类,然后为每个平台提供实际实现。对于 JVM,实际上并未使用类型参数 T,而对于本机平台,则按预期使用。

请记住,这种方法可能会有些令人困惑,因为在 JVM 实现中,类型参数 T 并不是真正必需的。这更像是一种解决方法,以保持不同平台之间的兼容性。

评论

0赞 hippietrail 5/5/2023
啊,人工智能聊天机器人提出了类似的东西,我不太明白,也无法开始工作。你的解释很好,很清楚。我认为可能有某种方法可以告诉它,我们不需要一个名为 DIR 的类型参数,而是使用 DIR 创建类型。我不知道什么术语,也不知道其他语言中是否有类似的东西,所以没有尝试解释它,并且还认为可能有另一种方法,这是有的。谢谢!
1赞 hippietrail 5/5/2023
实际上,这给了我这样的错误: 和Expected class 'PlatformDir' has no actual declaration in module multiplatform-test.jvmMain for JVM The following declaration is incompatible because number of type parameters is different: public actual typealias PlatformDir<T> = File defined in root package in file jvmMain.ktType arguments in the right-hand side of actual type alias should be its type parameters in the same order, e.g. 'actual typealias Foo<A, B> = Bar<A, B>'