Kotlin:如果 E 是实现接口(interface) I 的枚举类,则从返回类型为 Array<I> 的函数返回 Array<E>

标签 kotlin enums type-mismatch generic-variance

最近我遇到了一个问题,我有一个函数必须返回 I 的数组。 s,以枚举的所有值的形式E , 与 E实现接口(interface)I ,我想到的每个代码编译器都提示类型不匹配:

Error:(x, x) Kotlin: Type mismatch: inferred type is Array<E> but Array<I> was expected

一个最小的例子:
    interface I {}
    enum class E: I {
        A, B, C;
    }
    fun getMoreInterfaces(): Array<I> {
        return E.values()
    }

尝试分配 E.values() 时会发生这种情况。到 Array<I> 类型的变量
我很肯定这应该是可能的,因为 E实现 I .

我在测试时想到的另一件事是,当这样使用时它工作得很好:
    interface I {}
    enum class E: I {
        A, B, C;
    }
    fun getMoreInterfaces(): Array<I> {
        return arrayOf(E.A, E.B, E.C)
    }

我在这个话题上做了很多搜索,但没有运气(也许我选择了错误的方式来描述它?)

最佳答案

在 Kotlin 中,与 Java 不同,Array<T>T 上是不变的,所以,对于 E它是 I 的子类型, Array<E>Array<I>不是彼此的子类型。见:Variance .

鉴于 Array<T> types 还存储项目类型,不能完全受制unchecked casts ,解决此问题的最佳方法是创建一个单独的数组。

您可以通过手动创建一个数组并用项目填充它来做到这一点,例如在您的示例中(或使用构造函数 Array(n) { ... } ),或使用 .toTypedArray() 应用于数组的列表表示( .asList() ):

fun getMoreInterfaces(): Array<I> {
    return E.values().asList().toTypedArray()
}

(runnable sample)

但基本上,您可以使用 List<I>如果您不在性能关键代码中,这对于 Kotlin 来说比使用数组更惯用,而且也更简单。

另见:Difference between List and Array types in Kotlin

关于Kotlin:如果 E 是实现接口(interface) I 的枚举类,则从返回类型为 Array<I> 的函数返回 Array<E>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54200855/

相关文章:

android - kotlin 对象使用 Firebase 的空构造函数

swift - 返回动态类型的枚举方法

c++ 模板参数列表中参数 1 的类型/值不匹配

ms-access - VBA:rs.findfirst 中的类型不匹配

delphi - TADOQuery: 'EDatabaseError type mismatch for field ' MyField',期望:字符串实际:FixedWideChar'

java - 实现一个 kotlin 泛型函数,从复杂的 java 对象中检索特定字段

Android w/Kotlin pure-java-Junit NoClassDefFoundError 解决方法不起作用

kotlin - 如何降级 kotlin 版本

swift - 在没有 rawValue 的情况下使用 Swift 枚举作为 View 标签号

c++ - 对另一个模板函数 C++ 使用函数返回