2012-07-30 51 views
6

我移动我的第一个步骤,Scala和我想作以下的代码工作:协变T型发生在不变的位置

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

,而是因为我需要一个值,这并不能解决问题:pratically什么,我想说的是:“我不关心的插件ide类型,我知道基因会有一个返回其内容的基因场“。 (这里的+ T是因为我想做类似type Genome = Array[Gene[Any]]的东西,然后用它作为单个基因类的包装,所以我可以有一个异构数组类型) 是可以在Scala中完成它,或者我只是简单地错误的方法?如果使用不同的结构,比如Scala原生协变类,会更好吗?

在此先感谢!

P.S .:我也试过类和抽象类而不是特质,但总是相同的结果!

编辑:由迪迪埃杜邦样的建议,我来到这个代码:

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

所以我觉得现在我可以把和检索不同类型的数据,并与所有类型使用它们检查好吃的东西!

回答

9

数组是不变的,因为你可以写入它。

假设你做

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

这将崩溃(在您的实例的阵列是[字符串]也不会接受一个Date)。这就是编译器阻止这种情况的原因。

从那里,它很大程度上取决于您打算如何处理基因。您可以使用协变类型而不是Array(您可能会考虑Vector),但如果这是您的意图,那么这将阻止用户更改内容。你也可以在这个类里面有一个数组,只要它声明为private [this](这也会使得它很难改变内容)。如果您希望允许客户端突变基因的内容,则可能无法使Gene协变。

+0

不,我不需要改变它,我确实是关于Vector的。我的主要要求是让客户端代码管理不同的Gene [T]数组,但仍然对操作有类型限制。我知道这很困难,并且仍然处于第一步,也许我只是在思考过于实用,或者过于活跃,但我打算开发更大的东西,这可能是一个要求:自动装箱和取消装箱价值。如果你想要,我可以重述这个问题! – 2012-07-30 13:27:19

+0

请做。你做什么都行不通,但不知道你需要什么,很难提供更多的帮助。性能是你想要一个数组的原因吗?客户期望与Gene [T]的异质集合做什么? – 2012-07-30 14:23:58

+0

编辑我的答案。请检阅它,因为我认为感谢您的帮助,我找到了解决方案。显然我会接受你的答案;) – 2012-07-30 15:02:54

2

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

相关问题