Kotlin投影冗余

时间:2018-01-09 12:57:36

标签: java generics kotlin

在阅读关于Kotlin仿制品类型差异和投影的内容时,我想出了一个完全不熟悉的概念。有人可以解释一下作者想要解释的想法是什么?请引用 Kotlin in Action,MEAP

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

这里有两个具体问题:

  1. 为什么您需要在已投出的预计类型列表中添加投影?
  2. 即使您这样做,如何获得相同的列表?

2 个答案:

答案 0 :(得分:4)

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

以下是冗余客户端网站差异的示例:

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

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

另一方面,如果你已经使用了未在声明网站上投影的类型,那么它确实有意义。例如,Array类的方差不受限制:public class Array<T>

重写前一个示例以使用Array,添加out修饰符突然变得有意义,因为该参数仅用作T的生成者,即不在{{ 1}}位置。

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

in

经验法则

根据经验,对应于Java的 PECS (制作人fun <T> useArray(arr: Array<out T>) { println("first element: ${arr[0]}") } ,消费者extends),您可以记住 POCI < / strong> for Kotlin(制片人super,消费者out)。

答案 1 :(得分:2)

  
      
  1. 为什么您需要在已投出的预计类型列表中添加投影?
  2.   

你不会,但它可能偶然发生,例如通过重构或在深度调用链中,你忽略了传递的通用参数。

  
      
  1. 即使您这样做,如何获得相同的列表?
  2.   

类似地,您可以将投影视为幂等变换:out out Tout T相同。