Scala:特征内部的通用数组

时间:2014-06-13 06:06:03

标签: scala scala-collections

是否有可能构建subj?类似的东西:

trait THasArray[T]
{
  val ARRAY_SIZE = 8
  val array = Array.fill[T](ARRAY_SIZE)(null)
}

效果不好 - 编译器抱怨' null'这是我需要的。我知道Option,虽然问题是,是否可以使用普通数组。

感谢。

修改

谢谢你们两个人。 我已经发现了将类标记作为隐式参数传递的技巧。

尽管如此,我已经重新制定了我原来的问题。我需要将该数组初始化一次,并且永远不会改变。所以这里的解决方案并不需要隐式的val类型标记,而是使用init函数来实现这个技巧

trait THasArray[T >: Null]
{
  private var table: Seq[T] = null

  protected def init(elems: (Int, T)*)(implicit manifest: Manifest[T]) =
  {
    val size = (elems foldLeft 0)(_ max _._1)
    val array = Array.fill[T](size + 1)(null)
    elems foreach { x => array(x._1) = x._2 }
    table = array
  }
}

2 个答案:

答案 0 :(得分:2)

首先,方法Array.fill在范围内需要隐式ClassTag。其次,null的类型为Null,因此您需要将其强制转换为T。第三,array值应该是惰性的,因为ClassTag实例仅在HasArray创建时可用。

trait HasArray[T] {
  implicit def ev: ClassTag[T]
  def size: Int
  lazy val array = Array.fill[T](size)(null.asInstanceOf[T]) 
}

case class HasStringArray(size: Int)(implicit val ev: ClassTag[String]) extends HasArray[String]

scala> HasStringArray(8).array
res11: Array[String] = Array(null, null, null, null, null, null, null, null)

答案 1 :(得分:2)

T需要具有Null的下限,因为并非Scala中的所有值都可以为空。扩展AnyVal的类型由JVM原语表示,它们不能为空;例如,没有null Int

另外,请查看Array.fill的方法签名:

def fill[T: ClassTag](n: Int)(elem: => T): Array[T]

上下文绑定T: ClassTag表示fill具有类型为ClassTag[T]的隐式参数。特征的类型参数不能具有上下文绑定,因此遗憾的是,当您继承ClassTag时,您必须稍微偏离THasArray范围。< / p>

trait THasArray[T >: Null] {
  implicit def classTagT: ClassTag[T]
  val ARRAY_SIZE = 8
  lazy val array = Array.fill[T](ARRAY_SIZE)(null)
}

class Foo[T >: Null](implicit val classTagT: ClassTag[T])
  extends THasArray[T]