Kotlin 投影冗余

sun*_*r20 6 java generics kotlin

在阅读 Kotlin 泛型类型变化和投影时,我想到了一个完全陌生的概念。有人可以解释一下作者想要解释的想法是什么吗?请引用来自Kotlin in Action, MEAP 的引用:

获得out已经有out变化的类型参数的投影是没有意义的,例如List<out T>。这意味着与 相同List<T>,因为List被声明为class List<out T>。Kotlin 编译器会警告这样的投影是多余的。

这里有两个具体问题:

  1. 为什么您需要在已经输出的投影类型列表上添加投影?
  2. 即使你这样做了,你怎么得到同样的List?

s1m*_*nw1 6

正如所引述的那样,它将是“冗余的”,因此您永远不想这样做。它根本没有增加任何好处。整个引用与使用站点差异有关,即由客户端指定的差异(对应于 Java 中的通配符)。该类List<out T>已经有一个声明站点变化修饰符out,这使得使用站点应用程序out变得多余。

这是冗余客户端站点差异的示例:

fun <T> useList(list: List<out T>) {
    println("first element: ${list[0]}")
}
Run Code Online (Sandbox Code Playgroud)

我将out修饰符应用于type 的函数参数List<T>,这是使用站点差异的示例。编译器注意到它是多余的:"Projection is redundant". 它不会使情况变得更糟,也不会变得更好。

另一方面,如果您使用的类型尚未投影到声明站点上,则它确实有意义。例如,Array该类的方差不受限制:public class Array<T>

将前面的示例改写为 use Array,添加out修饰符突然变得有意义了,因为该参数仅用作 的生产者T,即不在in位置。

有意义的客户站点差异示例:

fun <T> useArray(arr: Array<out T>) {
    println("first element: ${arr[0]}")
}
Run Code Online (Sandbox Code Playgroud)

经验法则

根据经验,对应Java的PECS(Producer extends,Consumer super),你可以为Kotlin(Producer ,Consumer )记住POCIoutin