【问题标题】:Kotlin projection redundancyKotlin 投影冗余
【发布时间】:2018-01-09 12:57:35
【问题描述】:

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

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

这里有两个具体问题:

  1. 为什么需要在已经投影的类型 List 上添加投影?
  2. 即使你这样做了,你如何获得相同的列表?

【问题讨论】:

    标签: java generics kotlin


    【解决方案1】:

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

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

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

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

    另一方面,如果您使用的类型已经没有投射到声明站点,那么它确实有意义。例如,Array 类的方差不受限制:public class Array&lt;T&gt;

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

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

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

    经验法则

    根据经验,对应Java的PECS(生产者extends,消费者super),你可以为Kotlin记住POCI(生产者out,消费者in)。

    【讨论】:

      【解决方案2】:
      1. 为什么需要在已经投影的类型 List 上添加投影?

      您不知道,但它可能是偶然发生的,例如通过重构或在深层调用链中您忽略了传递的泛型参数。

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

      打个比方,您可以将投影视为幂等变换:out out Tout T 相同。

      【讨论】:

        猜你喜欢
        • 2011-06-12
        • 1970-01-01
        • 2019-04-05
        • 2018-06-18
        • 1970-01-01
        • 1970-01-01
        • 2017-11-08
        • 2018-01-01
        • 1970-01-01
        相关资源
        最近更新 更多