Kotlin投影冗余
在阅读关于Kotlin的genericstypes变化和投影时,我想出了一个完全陌生的概念。 有人可以解释一下作者想要解释的想法是什么? 请参阅Kotlin在行动中的引用,MEAP :
没有意义得到一个已经
out
差异的types参数的out
,例如List
。 这意味着与List
相同,因为List
被声明为class List
。 Kotlin编译器会警告这样的预测是多余的。
这里有两个具体的问题:
- 为什么你需要添加投影已经超出投影types列表?
- 即使你这样做,你如何得到相同的列表?
如引用,这将是“多余的”,因此你永远不会想这样做。 它根本不增加任何好处。 整个报价与使用地点差异相关 ,即客户指定的差异(对应于Java中的通配符)。 类List
已经有一个声明站点variables修饰符out
,这使得use-site应用程序变得冗余。
以下是冗余客户端站点差异的示例:
fun useList(list: List) { println("first element: ${list[0]}") }
我将out
修饰符应用于List
types的函数参数,这是使用站点方差的一个示例。 编译器注意到"Projection is redundant"
。 这并没有使情况变得更糟,也没有任何改善。
另一方面,如果你使用的是一个没有在声明网站上投影的types ,那么它是有道理的。 例如, Array
类的方差不受限制: public class Array
。
重写前面的例子来使用Array
,突然有意义的是添加一个out
修饰符,因为这个参数只被用作T
的生产者,即不在位置上。
有意义的客户站点变化示例:
fun useArray(arr: Array) { println("first element: ${arr[0]}") }
经验法则
作为一个经验法则,对应于Java的PECS (Producer extends
,Consumer super
),您可以记住Kotlin的POCI (Producer out
,Consumer in
)。
- 为什么你需要添加投影已经超出投影types列表?
你不这样做,但它可能是偶然发生的,比如通过重构,或者在深层调用链中,你忽略了被传递的generics参数。
- 即使你这样做,你如何得到相同的列表?
在一个比喻中,你可以把投影看作是一个幂等变换: out out T
和刚才out T
相同。