【问题标题】:Kotlin multiplatform support for OptionalKotlin 对 Optional 的多平台支持
【发布时间】:2019-11-23 10:39:06
【问题描述】:

我正在使用现在转换为 多平台 Kotlin 的 Java API。它曾经使用java.lang.Optional 作为许多调用的返回类型。我知道这是not the idiomatic Kotlin-way(请参阅discussion),但这是一个现有的API,可选保留(对于面向Java 的客户端来说,它也不是一个糟糕 选择)。我的问题是如何

注意:代码只需要return Optional.of(x)return Optional.empty()到外部API即可。任何内部使用都将被清除。

  • 我们如何使用 expect/actual/typealias 来使用 real Optional 类(如果可用)?
  • 有没有办法避免在非 Java 目标上重新实现 fake 可选类(即惯用地使用 nullable? 后缀)

【问题讨论】:

    标签: kotlin kotlin-multiplatform


    【解决方案1】:

    此时,Kotlin 不允许通过使用具有匹配 static 声明的 Java 类来为具有 companion object 的预期类提供 actual typealias。关注此问题以获取更新:KT-29882

    目前,您可以通过在预期的 Optional 类之外单独声明工厂函数来解决此问题,如下所示:

    expect class Optional<T : Any> {
        fun get(): T
        fun isPresent(): Boolean
        /* ... */
    }
    
    expect object Optionals {
        fun <T : Any> of(t: T): Optional<T>
        fun empty(): Optional<Nothing>
    }
    

    不一定是object,你可以使用顶级函数。

    然后,在 JVM 上,您必须为 Optional 类提供 actual typealias,此外,还需要为 Optionals 对象提供简单的实际实现:

    actual typealias Optional<T> = java.util.Optional<T>
    
    actual object Optionals {
        actual fun <T : Any> of(t: T): Optional<T> = java.util.Optional.of(t)
        actual fun empty(): Optional<Nothing> = java.util.Optional.empty()
    }
    

    至于不为非 JVM 平台提供实现,我怀疑这是可能的,因为这需要将 Optional 用法的一些非平凡的编译时转换为可空类型。所以你会想要这样的东西:

    actual typealias Optional<T> = T?
    

    现在是一个错误:

    类型别名扩展为T?,它不是类、接口或对象

    所以你实际上需要一个非 JVM 实现。为避免对每个非 JVM 目标重复它,您可以声明一个自定义源集并将其与特定于平台的源集链接,以便它们从那里获得实现:

    build.gradle.kts

    kotlin {
        /* targets declarations omitted */
    
        sourceSets {
            /* ... */
    
            val nonJvmOptional by creating {
                dependsOn(getByName("commonMain"))
            }
            configure(listOf(js(), linuxX64())) { // these are my two non-JVM targets
                compilations["main"].defaultSourceSet.dependsOn(nonJvmOptional)
            }
        }
    }
    

    然后,在这个自定义源集内(例如在 src/nonJvmOptional/kotlin/OptionalImpl.kt 中),您可以为非 JVM 目标提供实际实现。

    这是 Github 上的一个最小项目示例,我在其中进行了上述实验:h0tk3y/mpp-optional-demo

    【讨论】:

    • actual typealias Optional&lt;T&gt; = T? 如果它有效,那就太棒了。
    • @drekbour,据我所知,这几乎是这种类型别名唯一可行的用例,它需要不平凡的规则,这就是它被禁止的原因。
    猜你喜欢
    • 1970-01-01
    • 2013-02-22
    • 2018-01-04
    • 1970-01-01
    • 2022-12-22
    • 2023-01-27
    • 2012-02-11
    • 2017-06-05
    • 2016-10-18
    相关资源
    最近更新 更多