【问题标题】:covariant type T occurs in invariant position协变类型 T 出现在不变的位置
【发布时间】:2012-07-31 04:01:12
【问题描述】:

我正在 Scala 中迈出第一步,我想让以下代码工作:

trait Gene[+T] {
    val gene: Array[T]
}

编译器给出的错误是:covariant type T occurs in invariant position in type => Array[T] of value gene

我知道我可以这样做:

trait Gene[+T] {
    def gene[U >: T]: Array[U]
}

但这并不能解决问题,因为我需要一个值:实际上我想说的是“我不在乎内部类型,我知道基因将具有返回其内容的基因字段”。 (这里的 +T 是因为我想做type Genome = Array[Gene[Any]] 之类的事情,然后将其用作单个基因类的包装器,这样我就可以拥有异构数组类型) 是否可以在 Scala 中做到这一点,或者我只是采取了错误的方法?使用不同的结构会更好吗,比如 Scala 原生协变类?

提前致谢!

P.S.:我也尝试过使用类和抽象类而不是 trait,但结果总是一样!

编辑:在 Didier Dupont 的善意建议下,我来到了这段代码:

package object ga {


  class Gene[+T](val gene: Vector[T]){

    def apply(idx: Int) = gene(idx)

    override def toString() = gene.toString

  }

  implicit def toGene[T](a: Vector[T]) = new Gene(a)

  type Genome = Array[Gene[Any]]

}

package test

import ga._

object Test {
    def main(args: Array[String]) {
        val g = Vector(1, 3, 4)

        val g2 = Vector("a", "b")

        val genome1: Genome = Array(g, g2)

        println("Genome")

        for(gene <- genome1) println(gene.gene) 
    }
}

所以我现在认为我可以放入和检索不同类型的数据,并将它们与所有类型检查的好东西一起使用!

【问题讨论】:

    标签: scala covariance invariants


    【解决方案1】:

    数组是不变的,因为你可以在里面写。

    假设你这样做

    val typed = new Gene[String]
    val untyped : Gene[Any] = typed // covariance would allow that
    untyped.gene(0) = new Date(...)
    

    这会崩溃(您的实例中的数组是 Array[String] 并且不会接受 Date)。这就是编译器阻止这种情况的原因。

    从那里开始,这在很大程度上取决于您打算对 Gene 做什么。您可以使用协变类型而不是 Array(您可以考虑使用 Vector),但这会阻止用户改变内容,如果这是您想要的。你也可以在类中有一个数组,前提是它被声明为private [this](这也使得改变内容变得非常困难)。如果您希望允许客户端更改 Gene 的内容,则可能无法使 Gene 协变。

    【讨论】:

    • 不,我不需要改变它,而且我确实对 Vector 有兴趣。我的主要要求是让客户端代码管理一组不同的 Gene[T],但仍然对操作有类型限制。我知道这很困难,并且仍然处于我的第一步,也许我只是想太实用或太动态,但我打算开发更大的东西,这可能是一个要求:自动装箱和拆箱值。如果你愿意,我可以改写问题!
    • 请做。做什么都行不通,但不知道自己需要什么,就很难再帮上忙。性能是您想要阵列的原因吗?客户希望如何处理 Gene[T] 的异质集合?
    • 编辑了我的答案。请查看它,因为我认为感谢您的帮助,我找到了解决方案。显然我会接受你的回答;)
    • 我认为在您的代码 sn-p 中有一个错字。您声明了typed,但没有使用它。它应该在第二行而不是gene 对吧?
    【解决方案2】:

    gene 的类型需要在其类型参数中是协变的。为此,您必须选择不可变的数据结构,例如列表。但是您可以使用 scala.collection.immutable 包中的任何数据结构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-16
      • 1970-01-01
      • 1970-01-01
      • 2021-02-24
      • 2013-06-04
      • 2015-04-01
      相关资源
      最近更新 更多