Kotlin泛型中的输入和输出位置是什么? 我想从我知道的开始,或者至少我认为我知道的,这样我的问题会更清楚。

Kotlin泛型中的输入和输出位置是什么? 我想从我知道的开始,或者至少我认为我知道的,这样我的问题会更清楚。,kotlin,generics,Kotlin,Generics,首先,我知道您可以声明一个超类型的变量,并分配一个子类型的对象,以利用具有继承性和接口的多态性 我知道泛型提供了类型安全性,因为类型参数在定义上是不变的,所以在A是B的子类型的情况下,Foo不一定是Foo的子类型,并且根据对象的易变性,可能不会在适当的位置使用。这样,由于动态调度而在运行时可能出现的异常可以在编译时捕获 它们还有助于为不同类型定义通用逻辑:比如在列表中,您有类型a对象的集合,但它不会更改类型B对象的实现 另外,我理解了为什么MutableList不算作MutableList

首先,我知道您可以声明一个超类型的变量,并分配一个子类型的对象,以利用具有继承性和接口的多态性

  • 我知道泛型提供了类型安全性,因为类型参数在定义上是不变的,所以在A是B的子类型的情况下,
    Foo
    不一定是
    Foo
    的子类型,并且根据对象的易变性,可能不会在适当的位置使用。这样,由于动态调度而在运行时可能出现的异常可以在编译时捕获

  • 它们还有助于为不同类型定义通用逻辑:比如在列表中,您有类型a对象的集合,但它不会更改类型B对象的实现

  • 另外,我理解了为什么
    MutableList
    不算作
    MutableList
    的子类型,因为这可能会导致创建类型为
    MutableList
    的变量,该变量包含对
    MutableList
    对象的引用,并将
    Int
    元素添加到字符串列表中,这显然是个问题

  • 我还理解了为什么前面示例的列表版本可以工作,因为列表是不可变的,所以不能对对象进行任何可能导致类型不匹配的修改

  • 最后,我知道,
    in
    的类型参数只能用作正在使用的函数参数,而
    out
    的类型参数可以用作正在生成的函数返回类型


  • 现在谈谈我不明白的部分:
    • 我不太明白消费者生产者这两个词在
      输入
      输出
      方面的实际含义。类型处于消费或生产位置意味着什么?这是否意味着该类型的对象只能读或写?这和物体有什么关系吗

    • 如果我们不使用
      in
      out
      定义对象,或者相反,我们使用
      in
      out
      定义对象,而不是讨论我上面解释的子类型-超类型关系,那么对象的行为会是什么


    我花了几天的时间来研究不同的解释,但我发现缺乏例子是一个大问题,特别是因为我通常是这样学习的

    我可以在代码中使用这些概念,但缺乏基础知识或逻辑会让我非常不安,因此,如果您决定花时间写一篇解释,请提供一些例子和反例,说明某个想法为什么或如何工作。

    对您的第一个要点只做一个更正:列表不是一成不变的;它是只读的。列表可以是一个向上转换的可变实现,而引用它的其他对象可以对其进行变异

    Producer表示泛型类型在对象的任何函数或属性中显示为返回类型。例如,您可以从列表中获取T

    使用者表示泛型类型显示为任何函数的参数或对象的任何
    var
    属性的类型。例如,您可以将T放入可变列表中

    由于列表产生但不消耗(它没有任何以t作为参数的函数),因此它的类型在声明站点上被标记为仅产生,即协变,即
    out
    ,因此它的类型总是可以假定为
    out
    ,无论在何处使用,即使没有使用
    out
    关键字

    由于列表类型始终是协变的
    out
    ,因此任何列表都可以安全地向上转换为列表,其中该类型是原始类型的超类型。
    列表
    可以强制转换为
    列表
    ,因为从中得到的任何项(它产生的任何项)都将是字符串,因此也符合超类型CharSequence的条件

    相反的逻辑将适用于纯粹是消费者的东西,其类型在中标记为
    ,但很难给出一个简单的示例,在这个示例中,您将实际拥有这样一个有用的对象


    可变列表同时产生和使用,因此默认情况下它是不变的,但由于它也是一个列表,
    可变列表
    可以安全地转换为
    列表
    。如果有对
    列表的引用
    ,则可以从中获取字符序列。底层对象可能会继续从原始引用中放入新字符串。

    现在我看到了它,它们似乎被称为不可变而不是不可变,我甚至不知道这两个是分开的。此外,使用
    out
    类型参数定义的列表帮助我理解了生产者和只读概念,但是,缺少
    in
    的示例仍然是一个问题。如果更多的是放置一些Ts并仅使用受尊重的类型写入,那么我们应该能够将a的引用分配给a,因为
    中的
    具有相反的子类型关系(逆变),对吗?我在文档中没有看到“不可变”这个术语,它可以被解释为与不可变的意思完全相同<代码>列表
    被称为“只读”。在Venkat Subramaniam的《编程Kotlin》一书中,有一个伟大的章节“泛型:参数类型的变化和约束”,我认为它完美地涵盖了这个主题(以及许多其他主题)。