如何使用Scala中的默认值初始化通用数组

时间:2016-12-28 18:43:45

标签: arrays scala generics

尝试使用泛型类型初始化数组并将其存储在值(val)中时遇到麻烦

case class Matrix[T <: AnyVal](val structure : Array[Array[Array[T]]])

//A method in another class
def foo() : Unit = {
    val aux: Array[Array[Array[T]]] = Array.fill(this.structure.length, this.structure.head.length, this.structure.head.head.length)(null)
    ...
    ...
}

问题在于,在尝试创建T类型的数组时,我想用默认值null初始化它,但它说:

Array [Array [Array [T]]]类型的表达式不符合预期类型Array [Array [Array [T]]]

我该如何解决这个问题?谢谢

2 个答案:

答案 0 :(得分:1)

T:Numeric

如果我是你,我会将T限制为Numeric类型,然后使用zero值作为空矩阵的默认值:

scala> :pa
// Entering paste mode (ctrl-D to finish)

import scala.reflect.ClassTag

class Matrix[T:Numeric](val structure: Array[Array[T]])
{
    def *(that: Matrix[T]): Matrix[T] = ???
    def +(that: Matrix[T]): Matrix[T] = ???
    override def toString: String = structure.map(_.mkString(",")).mkString("\n")
}

object Matrix
{
    def apply[T:Numeric:ClassTag](rows: Int, cols: Int): Matrix[T] =
    {
        val zero: T = implicitly[Numeric[T]].zero
        new Matrix[T](Array.fill[T](rows, cols)(zero))
    }

    def apply[T:Numeric](data: Array[Array[T]]): Matrix[T] = new Matrix(data)
}

// Exiting paste mode, now interpreting.

import scala.reflect.ClassTag
defined class Matrix
defined object Matrix

scala> val empty = Matrix[Int](3,3)
empty: Matrix[Int] =
0,0,0
0,0,0
0,0,0

scala> val ex = Matrix[Int](Array(Array(1,2), Array(3,4)))
ex: Matrix[Int] =
1,2
3,4

T <: AnyRef

否则,如果您想使用null作为默认值的非数字值,您可以执行以下操作:

scala> :pa
// Entering paste mode (ctrl-D to finish)

import scala.reflect.ClassTag

class Matrix[T >: Null <: AnyRef](val structure : Array[Array[T]])
{
    override def toString: String = structure.map(_.mkString(",")).mkString("\n")
}

object Matrix
{
    def apply[T >: Null <: AnyRef : ClassTag](rows: Int, cols: Int): Matrix[T] =
    {
        new Matrix[T](Array.fill[T](rows, cols)(null))
    }

    def apply[T >: Null <: AnyRef](data: Array[Array[T]]): Matrix[T] = new Matrix(data)
}

// Exiting paste mode, now interpreting.

import scala.reflect.ClassTag
defined class Matrix
defined object Matrix

scala> case class Person(name: String)
defined class Person

scala> val empty = Matrix[Person](3,3)
empty: Matrix[Person] =
null,null,null
null,null,null
null,null,null

scala> val data = Array(Array(Person("a"), Person("b")), Array(Person("c"), Person("d")))
data: Array[Array[Person]] = Array(Array(Person(a), Person(b)), Array(Person(c), Person(d)))

scala> val ex = Matrix[Person](data)
ex: Matrix[Person] =
Person(a),Person(b)
Person(c),Person(d)

请注意,您必须通过添加绑定T来手动指定Null可以是T >: Null的超类型。

答案 1 :(得分:1)

如果您想要默认值,只需使用Array.ofDim(this.structure.length, this.structure.head.length, this.structure.head.head.length)代替Array.fill。这些值与Java类似,对象为null0Int0.0Double等。它也更便宜。

您在范围内需要ClassTag[T],但您也需要fill