Kotlin 泛型声明站点差异 构造

2024-03-24

我正在阅读有关 kotlin 没有通配符的原因(https://kotlinlang.org/docs/reference/generics.htm https://kotlinlang.org/docs/reference/generics.htmll)。这一切都源于申报地点的差异。我们有<in T> and <out T>应取代通配符的结构。我想我明白了<out T>有效,但我有麻烦<in T>.
所以在java中我们可以这样写:

public List<? extends Number> list1;
public List<? super String> list2;

初始化后的第一种情况成为只读列表(尽管不是完全不可变,因为我们可以清除它),如果我们将每个元素视为数字,则可以读取该列表。
第二种情况是只写(尽管如果我们将每个元素都视为对象,我们就可以读取它)。我们可以在那里编写 String 及其子类。
在 Kotlin 中,我能够使用以下命令重新创建 list1 示例<out T>像这样:

class Service {
  val container = Container(mutableListOf("1", "2", "3"))
}
class Container<T>(var list1: MutableList<out T>)

Finally I tried something similar with <in T> thinking that I could recreate list2 example, but I failed: enter image description here

有人可以向我解释如何在 Kotlin 中实现我的 list2 示例吗?我应该如何使用<in T>施工方法得当吗?


Kotlin List<E>不等同于JavaList<E>。 Java 列表具有变异函数,而 Kotlin 列表是只读的。这是科特林MutableList<E>这相当于 Java 列表。

接下来,看看List<E>宣言 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html:它的类型参数是协变的(out E),并且声明站点差异不能被使用站点差异覆盖,这就是为什么你不能拥有List<in T>.

Moreover, the declaration-site variance out E means that E never appears in an in-position (there's no function parameter of type E and no mutable property of type E), and indeed, since List<E> is read-only, it doesn't take E into any of its functions (*).

您可以将示例转换为使用MutableList<E> https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/index.html反而:

class Container2<T>(var list2: MutableList<in T>)

The MutableList<E>接口有其E不变,并且in- 使用地点的投影与声明地点的差异不冲突。

(*) Actually, it does https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/contains.html, but only using the parameters that are marked with the @UnsafeVariance https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-unsafe-variance/index.html annotation, which simply suppresses the variance conflict, more about it can be found here https://blog.jetbrains.com/kotlin/2015/10/kotlin-1-0-beta-candidate-is-out/.


另外,还有一点小意见:

这一切都源于申报地点的差异。我们有<in T> and <out T>应取代通配符的结构。

它实际上是使用站点差异取代了 Java 通配符。声明站点差异仅应用于类型参数声明(定义类型的地方),并且当它是时,该类型的所有用法都将具有该差异(例如,当您使用List<CharSequence>,它实际上是一个List<out CharSequence>由于声明地点的差异List<out E>)。因此,使用地点差异适用于通用类型的特定用法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kotlin 泛型声明站点差异 构造 的相关文章

随机推荐