Kotlin泛型声明站点差异< in T>建造 [英] Kotlin Generics declaration-site variance <in T> construction

查看:106
本文介绍了Kotlin泛型声明站点差异< in T>建造的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读Kotlin没有通配符的原因( https://kotlinlang.org /docs/reference/generics.htm l).一切都到了申报地点的差异.我们有<in T><out T>构造应替换通配符.我想我了解<out T>的工作原理,但是我对<in T>有麻烦.
因此,在Java中,我们可以这样写:

I was reading about reasons why kotlin does not have wildcards (https://kotlinlang.org/docs/reference/generics.html). It all came to the declaration-site variance. We have <in T> and <out T> constructions which should replace wildcards. I think I understood how <out T> works but I have troubles with <in T>.
So in java we could write something like this:

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

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

First case after initialization becomes read only list (though not perfectly immutable cause we could clear it) which could be read if we treat every element as Number.
Second case is write only (though we could read it if we treat every element as Object). We could write there String and it subclasses.
In Kotlin I was able to recreate list1 example using <out T> like this:

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

最后,我尝试了与<in T>类似的操作,以为可以重新创建list2示例,但是失败了:

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

有人可以向我解释如何在Kotlin中实现我的list2示例吗?我应该如何正确使用<in T>构造?

Can someone explain to me how to achieve my list2 example in Kotlin? How should I use <in T> construction in proper way?

推荐答案

Kotlin List<E>不等同于Java List<E>. Java列表具有变异功能,而Kotlin列表是只读的.是Kotlin MutableList<E>等效于Java列表.

Kotlin List<E> is not equivalent to Java List<E>. The Java list has the mutating functions, while the Kotlin list is read-only. It's Kotlin MutableList<E> that is equivalent to the Java list.

接下来,看看 声明:其类型参数为协变(out E),并且声明站点的方差不能被使用站点的方差覆盖,这就是为什么您不能拥有List<in T>的原因.

Next, take a look at the List<E> declaration: its type parameter is covariant (out E), and the declaration-site variance cannot be overridden by use-site variance, that's why you cannot have a List<in T>.

此外,声明位置差异out E表示E永远不会出现在in-位置(没有类型为E的函数参数,也没有类型为E的可变属性),实际上,由于List<E>是只读的,因此它不会将E纳入其任何功能(*).

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> 代替:

You can convert your example to use MutableList<E> instead:

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

MutableList<E>接口具有其E不变式,并且使用位置的in-投影与声明位置的差异不冲突.

The MutableList<E> interface has its E invariant, and the in-projection at use-site does not conflict with declaration-site variance.

(*)实际上,,但仅使用标有 @UnsafeVariance 批注,它只是抑制了方差冲突,有关它的更多信息,请参见

(*) Actually, it does, but only using the parameters that are marked with the @UnsafeVariance annotation, which simply suppresses the variance conflict, more about it can be found here.

还有一点点话:

这一切都到了申报地点的差异.我们有<in T><out T>构造应替换通配符.

It all came to the declaration-site variance. We have <in T> and <out T> constructions which should replace wildcards.

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

It's actually use-site variance that replaces Java wildcards. Declaration-site variance is only applied at the type parameter declaration (where the type is defined), and when it is, all the usages of the type will have that variance (e.g. when you use List<CharSequence>, it's actually a List<out CharSequence> because of the declaration-site variance of List<out E>). And use-site variance is, accordingly, for particular usages of a generic type.

这篇关于Kotlin泛型声明站点差异&lt; in T&gt;建造的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆