函数结果如 List<?在 Kotlin 中扩展 Base>
Function result like List<? extends Base> in Kotlin
我在 Java 中有这个,但不知何故我无法找到在 Kotlin 中指定 getStuff()
的 return 类型的正确方法。
class Base {
}
class Extended extends Base {
}
List<? extends Base> getStuff() {
return new ArrayList<Extended>();
}
List<Extended> foo = new ArrayList<>();
foo.addAll((List<Extended>)getStuff());
当我像这样将 getStuff()
函数转换为 Kotlin 时
fun getStuff(): List<Base> { ... }
我在 Java 的 foo.addAll((List<Extended>)getStuff());
中得到一个编译器错误说
List 无法转换为 List
我发现的唯一方法是使用 getStuff() return List<*> 但这似乎不对。
这似乎是 Kotlin 支持 declaration-site 方差但 Java 不支持的方式造成的怪癖。在 Kotlin 中 <? extends Base>
等价于 <out Base>
。在 Kotlin 中,read-only List 接口在声明站点已经是 <out T>
,因此在使用 read-only 列表时通常不需要指定 out
。但是当一个 List 返回到 Java 代码时,Java 看不到声明位置的差异,因此它认为它是一个不变的 T。你可以在 use-site 处显式标记差异:
fun getStuff(): List<out Base> { ... }
但是 Java 似乎仍然认为它在我的实验中是不变的。我认为 Kotlin 不会费心应用 use-site 方差,因为它在 Kotlin 方面是多余的。
在 Java 方面解决这个问题的一种方法是转换为协变类型,然后再转换为您的其他类型:
List<Extended> foo = new ArrayList<>();
foo.addAll((List<Extended>)(List<? extends Base>)getStuff());
或者,你可以在 Kotlin 中将其更改为 MutableList,这样使用 use-site 方差并不多余:
fun getStuff(): MutableList<out Base> { ... }
无论哪种方式,这都是不安全的转换,因为 Java 中的 getStuff()
返回的 List 或 Kotlin 可能包含 Base 的子类型但不是 Extended 的元素。这可以解释为什么 Kotlin 设计者没有尝试“修复”您 运行 遇到的问题。它只会启用不安全的代码。
我在 Java 中有这个,但不知何故我无法找到在 Kotlin 中指定 getStuff()
的 return 类型的正确方法。
class Base {
}
class Extended extends Base {
}
List<? extends Base> getStuff() {
return new ArrayList<Extended>();
}
List<Extended> foo = new ArrayList<>();
foo.addAll((List<Extended>)getStuff());
当我像这样将 getStuff()
函数转换为 Kotlin 时
fun getStuff(): List<Base> { ... }
我在 Java 的 foo.addAll((List<Extended>)getStuff());
中得到一个编译器错误说
List
我发现的唯一方法是使用 getStuff() return List<*> 但这似乎不对。
这似乎是 Kotlin 支持 declaration-site 方差但 Java 不支持的方式造成的怪癖。在 Kotlin 中 <? extends Base>
等价于 <out Base>
。在 Kotlin 中,read-only List 接口在声明站点已经是 <out T>
,因此在使用 read-only 列表时通常不需要指定 out
。但是当一个 List 返回到 Java 代码时,Java 看不到声明位置的差异,因此它认为它是一个不变的 T。你可以在 use-site 处显式标记差异:
fun getStuff(): List<out Base> { ... }
但是 Java 似乎仍然认为它在我的实验中是不变的。我认为 Kotlin 不会费心应用 use-site 方差,因为它在 Kotlin 方面是多余的。
在 Java 方面解决这个问题的一种方法是转换为协变类型,然后再转换为您的其他类型:
List<Extended> foo = new ArrayList<>();
foo.addAll((List<Extended>)(List<? extends Base>)getStuff());
或者,你可以在 Kotlin 中将其更改为 MutableList,这样使用 use-site 方差并不多余:
fun getStuff(): MutableList<out Base> { ... }
无论哪种方式,这都是不安全的转换,因为 Java 中的 getStuff()
返回的 List 或 Kotlin 可能包含 Base 的子类型但不是 Extended 的元素。这可以解释为什么 Kotlin 设计者没有尝试“修复”您 运行 遇到的问题。它只会启用不安全的代码。