我正在阅读kotlin没有通配符的原因(https://kotlinlang.org/docs/reference/generics.htm l)。这一切都来自声明网站的差异。我们有<in T>
和<out T>
构造,应该替换通配符。我想我理解<out T>
是如何运作的,但我对<in T>
有麻烦。
所以在java中我们可以写这样的东西:
public List<? extends Number> list1;
public List<? super String> list2;
初始化后的第一种情况变为只读列表(虽然不完全不可变,因为我们可以清除它),如果我们将每个元素都视为数字,则可以读取。
第二种情况是只写(虽然我们可以读取它,如果我们将每个元素视为对象)。我们可以写String和它的子类。
在Kotlin中,我能够使用<out T>
重新创建list1示例,如下所示:
class Service {
val container = Container(mutableListOf("1", "2", "3"))
}
class Container<T>(var list1: MutableList<out T>)
最后,我尝试了与<in T>
同心的事情,认为我可以重新创建list2示例,但是我失败了:
有人可以向我解释如何在Kotlin中实现我的list2示例吗?我该如何以正确的方式使用<in T>
构造?
答案 0 :(得分:4)
Kotlin List<E>
不等同于Java List<E>
。 Java列表具有变异功能,而Kotlin列表是只读的。它是Kotlin MutableList<E>
,相当于Java列表。
接下来,看一下List<E>
declaration:它的类型参数是covariant(out E
),并且使用站点方差不能覆盖声明站点差异,这就是为什么你不能拥有List<in T>
。
此外,声明网站差异out E
表示E
永远不会出现在in
- 位置(没有E
类型的函数参数,也没有E
的可变属性类型List<E>
),实际上,由于E
是只读的,因此class Container2<T>(var list2: MutableList<in T>)
不会将MutableList<E>
带入任何函数(*)。
您可以将示例转换为使用MutableList<E>
代替:
E
in
界面有<in T>
不变量,<out T>
- 使用网站上的投影与声明网站差异不冲突。
(*)实际上,it does,但只使用标有@UnsafeVariance
注释的参数,这些参数只是抑制方差冲突,可以找到更多关于它的{{3} }。
另外,一句小话:
这一切都来自声明网站的差异。我们有
List<CharSequence>
和List<out CharSequence>
构造,应该替换通配符。
实际上是使用站点方差取代了Java通配符。声明 - 站点方差仅应用于类型参数声明(定义类型的位置),并且当它是时,该类型的所有用法都将具有该方差(例如,当您使用List<out E>
时,它实际上是{ {1}}因为y_train
的声明 - 网站差异。因此,使用站点方差适用于泛型类型的特定用法。