我正在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,但是结果总是一样!

编辑:在迪迪埃·杜邦的建议下,我来到了这段代码:

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)
    }
}


因此,我现在认为我可以放置和检索不同类型的数据,并将其与所有类型检查对象一起使用!

最佳答案

数组是不变的,因为您可以在其中写入。

假设你做

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),但是如果您打算这样做的话,这将阻止用户更改内容。您也可以在类中包含一个Array,条件是将其声明为private [this](这也将使更改内容也变得非常困难)。如果您希望允许客户突变基因的内容,则可能无法使基因协变。

08-26 15:28
查看更多