2011-11-13 44 views
3

我正在寻找在数组实例化中提供类清单的建议。我已经重构这个代码(编译罚款):缺少抽象类型成员数组的类清单

trait Ref[A] 
trait Struct[A] { 
    val arr = new Array[Ref[A]](1) 
} 

这样:

trait Ref[S <: Sys[S], A] 
trait Sys[Self <: Sys[Self]] { 
    type R[A] <: Ref[Self, A] 
} 

trait Struct[S <: Sys[S], A] { 
    val arr = new Array[S#R[A]](1) 
} 

这种失败消息"cannot find class manifest for element type S#R[A]"

那么我将如何解决这个问题?

回答

2

您的问题是Array是在其类型参数不变的,需要精确的类型参数。您在Sys中的type R的定义仅提供上限。

您可以通过与平等替换上R上限在定义现场解决问题,

trait Ref[S <: Sys[S], A] 
trait Sys[Self <: Sys[Self]] { 
    type R[A] = Ref[Self, A]  // '=' not '<:' 
} 

trait Struct[S <: Sys[S], A] { 
    val arr = new Array[S#R[A]](1) // OK 
} 

或者,如果你愿意离开R[A]开在Sys可以指定等式约束在通过细化,像这样使用网站,

trait Ref[S <: Sys[S], A] 
trait Sys[Self <: Sys[Self]] { 
    type R[A] <: Ref[Self, A]  // Back to an upper bound 
} 

trait Struct[S <: Sys[S] { type R[A] = Ref[S, A] }, A] { 
//      ^^^^^^^^^^^^^^^^^^^^^^^^^ 
//      Assert the equality via a refinement 
    val arr = new Array[S#R[A]](1) // OK 
} 

如果不能牵制在这两种方式type R,那么你别无选择,只能提供ClassManifest明确自己,

trait Ref[S <: Sys[S], A] 
trait Sys[Self <: Sys[Self]] { 
    type R[A] <: Ref[Self, A] 
} 

trait Struct[S <: Sys[S], A] { 
    implicit val rM : ClassManifest[S#R[A]] // Provided manifest later ... 
    val arr = new Array[S#R[A]](1) // OK 
} 

class SomeSys extends Sys[SomeSys] { 
    type R[A] = Ref[SomeSys, A] 
} 

val s = new Struct[SomeSys, Int] { 
    val rM = implicitly[ClassManifest[SomeSys#R[Int]]] 
    //        ^^^^^^^^^^^^^^ 
    //        Precise type known here 
} 

哪些挑选取决于你的大背景。

+0

谢谢。我想我需要用'隐式[ClassManifest []]''的最后一种方法。 –

2

我可以想出一个解决方案,它涉及一个简单的间接:

trait Sys[Self <: Sys[Self]] { 
    type R[A] <: Ref[Self, A] 
    def newRefArray[A](size: Int): Array[Self#R[A]] 
} 

trait Struct[S <: Sys[S], A] { 
    def sys: S 
    val arr = sys.newRefArray[A](1) 
}