【问题标题】:Kotlin type inference for multiple possible types?多种可能类型的 Kotlin 类型推断?
【发布时间】:2020-08-19 17:11:00
【问题描述】:

我有一个函数,它采用两种可能类型的参数metadata:Metadata1 或 Metadata2。我正在尝试编写一个可用于两者的实用程序函数,因为有大量的代码重用。它们都有一个 DataPoint 对象列表,每个对象都有 name() 方法。

我认为在我的代码中 Kotlin 会使用类型推断来知道 dataPoints 只能是两种都具有 DataPoint.name() 方法的类型之一,但我得到的是“未解析的引用:名称”。我怎样才能使这个函数足够通用以适用于 Metadata1 和 Metadata2?

var dataPoints: List<Any>
if (metadata is Metadata1) {
    dataPoints = metadata.metadata1().dataPoints()
} else {
    dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
    textView.test = dataPoints.fold("")
    { x, dataPoint ->
        x + dataPoint.name() + " \n" // unresolved reference: name
    }
}

【问题讨论】:

  • 不,Kotlin 没有联合类型。另外,您声明了List&lt;Any&gt;。这两个类有共同的接口还是超类?
  • 您应该创建两个类都实现的接口(例如,定义了name() 函数)。
  • Metadata1Metadata2 必须 有一些共享的超类型:接口、类、密封类(这将保证它始终是这两者之一).. .没有它,你基本上无能为力。 (好吧,您可以创建一个密封的类来保存 Metadata1Metadata2,但这会在调用方方面增加更多工作。)
  • 我最终通过将 dataPoints 映射到 Metadata1 和 Metadata2 的单个共享类型并将其作为共享类型参数直接传递给函数来解决了这个问题。谢谢大家!
  • 两个类都可能有一个方法称为 name(),但如果它们继承自同一个类或接口,它只是同一个方法。否则,它们是完全不同的、不相关的方法,只是碰巧拼写相同。

标签: kotlin


【解决方案1】:

这不是 Kotlin 独有的,静态类型的 OOP 语言就是这样工作的。

您的 dataPoints 是 List&lt;Any&gt; 类型,而 Any 没有 name() 函数。你没有显示很多代码,所以我不知道你有什么样的对象。

这是关于运行时与编译时的对比。编译器无法预测您将在运行时将哪些类型放入List&lt;Any&gt;,因此您可以对其成员调用的唯一函数是属于Any 类的函数。想象一下,如果该列表包含一个没有 name() 函数的对象。如果编译器允许您调用 name(),那么您将遇到运行时崩溃。这就是为什么您在尝试时会遇到编译器时错误。

如果列表中有两种不同类型的对象,一种方法是创建一个接口,它们都使用接口中的共享方法实现。看起来像这样:

interface Name {
    fun name()
}

将 dataPoints 更改为 List&lt;Name&gt;,让您的数据类实现它,现在 dataPoint.name() 编译,因为列表中唯一允许的对象是具有 name() 函数的 Name 类型的对象。

var dataPoints: List<Name>
if (metadata is Metadata1) {
    dataPoints = metadata.metadata1().dataPoints()
} else {
    dataPoints = (metadata as Metadata2).metadata2().dataPoints()
}
if (data.size > 1) {
    textView.test = dataPoints.fold("")
    { x, dataPoint ->
        x + dataPoint.name() + " \n" // Compiles now
    }
}

您的 Metadata1 和 Metadata2 类也有类似的问题,它们可能应该实现一个接口或扩展一个超类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    相关资源
    最近更新 更多