使用带抽象类型的Scala数组

时间:2017-03-10 14:37:00

标签: java scala

作为一个例子,这是一个简单的代码。

trait DataType {
    type DType
    // more stuff
}

object IntType extends DataType {
    type DType = Int
    // more stuff
}

trait Codec {
    val dtype: DataType
    // more stuff
}

class DenseCodec(val dtype: DataType) extends Codec {
    def get(size: Int) = new Array[dtype.DType](size)
}

val dense = new DenseCodec(IntType)

dense.get(4)

这不会编译:

cannot find class tag for element type DenseCodec.this.dtype.DType def get(size: Int) = new Array[dtype.DType](size) ^

我知道这与Scala中的Arrays特殊有关。我可以在这里使用类似Vector的东西,它可以正常工作,但我正在研究的项目对数据处理很重要,我希望尽可能保持高效。

1 个答案:

答案 0 :(得分:2)

这将有效

  def get(size: Int)(implicit tag: ClassTag[DataType]) = new Array[DataType](size)

或使用等效的上下文绑定

  def get[DType: ClassTag](size: Int) = new Array[DType](size)

您甚至可以使用模板DType替换T

Array's构造函数实际上采用类型为ClassTag的隐式参数,因此您需要隐式或显式地提供一个参数。

编辑:另外值得注意的是,使用dtype.DType无法使用,因为dtype的类型DataType没有具体的DType,只有一个抽象的dtype.type。有趣的val dtype: DataType可以正常工作,因为在运行时IntType已经是import scala.reflect.ClassTag object Types { trait DataType[A] { // more stuff } object IntType extends DataType[Int] object StringType extends DataType[String] trait Codec[B] { val dtype: DataType[B] // more stuff } class DenseCodec[B](val dtype: DataType[B]) extends Codec[B] { def get(size: Int)(implicit ct: ClassTag[B]) = new Array[B](size) } def main(args: Array[String]): Unit = { val denseInt = new DenseCodec(IntType) val arrInt = denseInt.get(4) //Array[Int] val denseString = new DenseCodec(StringType) val arrString = denseString.get(4) //Array[String] } }

EDIT2:如果你想传播这种类型,我担心唯一的方法就是使用类型类。

DType

这样你可以摆脱IntType并使用类型类的类型。您没有介绍任何样板文件,因为您想要定义DType并且可能还有更多类型。 希望这个解决你的问题:)

EDIT3:如果你想让你的trait DataType[A] { type DType = A // more stuff } 继续

get

并修改def get(size: Int)(implicit ct: ClassTag[B]) = new Array[dtype.DType](size) 定义

IntType

但是这样你就会得到一个来自StringTypevkQueueWaitIdle等的长型签名。