Kotlin:如果 E 是实现接口 I 的枚举 class,则从具有 return 类型 Array<I> 的函数返回 Array<E>
Kotlin: Returning Array<E> from function with return type Array<I> if E is enum class that implements interface I
最近我 运行 遇到一个问题,我有一个函数必须 return 一个 I
的数组,以枚举 E
的所有值的形式,E
实现接口 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
上是不变的,因此,对于 I
的子类型 E
,Array<E>
和 Array<I>
不是彼此的子类型。参见:Variance.
鉴于 Array<T>
类型也存储项目类型并且不能完全 unchecked casts,解决此问题的最佳方法是创建一个单独的数组。
您可以通过手动创建数组并用项目填充它来做到这一点,就像在您的示例中一样(或使用构造函数 Array(n) { ... }
), or use .toTypedArray()
applied to the list representation of the array (.asList()
):
fun getMoreInterfaces(): Array<I> {
return E.values().asList().toTypedArray()
}
但基本上,如果您不在性能关键代码中,您可以直接使用 List<I>
,这对于 Kotlin 来说比使用数组更惯用,也更简单。
另请参阅:
Array
是 Kotlin 中的不变泛型,所以如果你需要 return Array<I>
的一个实例,你不能 return Array<E>
相反,即使 E
是 I
.
的子类型
但如果您仅 使用 数组中的 return 值,则可以将其类型声明为 Array<out I>
。此类型是 Array<I>
类型的协变投影,它允许您 return 同时 Array<I>
和 Array<E>
.
interface I {}
enum class E: I {
A, B, C
}
fun getMoreInterfaces(): Array<out I> {
return E.values()
}
最近我 运行 遇到一个问题,我有一个函数必须 return 一个 I
的数组,以枚举 E
的所有值的形式,E
实现接口 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
上是不变的,因此,对于 I
的子类型 E
,Array<E>
和 Array<I>
不是彼此的子类型。参见:Variance.
鉴于 Array<T>
类型也存储项目类型并且不能完全 unchecked casts,解决此问题的最佳方法是创建一个单独的数组。
您可以通过手动创建数组并用项目填充它来做到这一点,就像在您的示例中一样(或使用构造函数 Array(n) { ... }
), or use .toTypedArray()
applied to the list representation of the array (.asList()
):
fun getMoreInterfaces(): Array<I> {
return E.values().asList().toTypedArray()
}
但基本上,如果您不在性能关键代码中,您可以直接使用 List<I>
,这对于 Kotlin 来说比使用数组更惯用,也更简单。
另请参阅:
Array
是 Kotlin 中的不变泛型,所以如果你需要 return Array<I>
的一个实例,你不能 return Array<E>
相反,即使 E
是 I
.
但如果您仅 使用 数组中的 return 值,则可以将其类型声明为 Array<out I>
。此类型是 Array<I>
类型的协变投影,它允许您 return 同时 Array<I>
和 Array<E>
.
interface I {}
enum class E: I {
A, B, C
}
fun getMoreInterfaces(): Array<out I> {
return E.values()
}