协变类型T发生在不变位置 [英] covariant type T occurs in invariant position

查看:142
本文介绍了协变类型T发生在不变位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Scala中迈出第一步,我想使以下代码有效:

I'm moving my first steps in Scala and I would like to make the following code works:

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

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

The error that the compiler gives is: covariant type T occurs in invariant position in type => Array[T] of value gene

我知道我可以做类似的事情:

I know I could do something like:

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

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

but this doesn't solve the problem because I need a value: pratically what I'm trying to say is "I don't care of the inside type, I know that genes will have a gene field that return its content". (the +T here is because I wanna do something like type Genome = Array[Gene[Any]] and then use it as a wrapper against the single gene classes so I can have a heterogeneous array type) Is it possible to do it in Scala or I'm simply taking a wrong approach? Would it be better to use a different structure, like a Scala native covariant class?

提前谢谢!

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

P.S.: I've also tried with class and abstract class instead than trait but always same results!

在迪迪埃·杜邦(Didier Dupont)的善意建议下,我来到了这段代码:

with kind suggestion by Didier Dupont I came to this code:

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

所以我现在认为我可以放置和检索不同类型的数据,并将它们用于所有类型检查的东西!

So I now think I can put and retrieve data in different types and use them with all type checking goodies!

推荐答案

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

Array is invariant because you can write in it.

假设您这样做

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

这将崩溃(您实例中的数组是Array [String],并且不接受日期).这就是为什么编译器阻止这种情况的原因.

this would crash (the array in your instance is an Array[String] and will not accept a Date). Which is why the compiler prevents that.

从那里开始,这在很大程度上取决于您打算对Gene做些什么.您可以使用协变类型来代替Array(可以考虑使用Vector),但是如果您打算这样做的话,这将阻止用户更改内容.您也可以在类中使用Array,条件是将其声明为private [this](这也将使更改内容变得相当困难).如果您希望允许客户端突变Gene的内容,则可能无法使Gene协变.

From there, it depends very much on what you intend to do with Gene. You could use a covariant type instead of Array (you may consider Vector), but that will prevent user to mutate the content, if this was what you intended. You may also have an Array inside the class, provided it is decladed private [this] (which will make it quite hard to mutate the content too). If you want the client to be allowed to mutate the content of a Gene, it will probably not be possible to make Gene covariant.

这篇关于协变类型T发生在不变位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆