Java 使用抽象类型的Scala数组

Java 使用抽象类型的Scala数组,java,scala,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 Cod

下面是一个简单的代码示例

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)
这将不会编译:

找不到元素类型DenseCodec.this.dtype.dtype的类标记
def get(size:Int)=新数组[dtype.dtype](大小)
^

我知道这与Scala中的数组的特殊性有关。我可以在这里使用Vector之类的工具,它可以很好地工作,但我正在进行的项目需要大量的数据处理,我希望尽可能地保持效率。

这将起作用

  def get(size: Int)(implicit tag: ClassTag[DataType]) = new Array[DataType](size)
或者使用等效的上下文绑定

  def get[DType: ClassTag](size: Int) = new Array[DType](size)
您甚至可以用模板
T
替换
DType

数组的
构造函数实际上接受类型为
ClassTag
的隐式参数,因此您需要隐式或显式地提供一个参数

编辑:还值得注意的是,使用
dtype.dtype
将不起作用,因为
dtype
属于
DataType
类型,它没有具体的
dtype
,而只是一个抽象的类型。有趣的是,
dtype.type
可以正常工作,因为在运行时
valdtype:DataType
已经是
IntType

EDIT2:如果你想传播类型,恐怕唯一的方法就是使用类型类

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]
  }
}
这样,您就可以去掉
DType
,而改用type类的类型。您不引入任何样板文件,因为您想定义
IntType
,而且可能还要定义更多类型。 希望这个能解决你的问题:)

编辑3:如果你想保留你的
DType
只需使用

trait DataType[A] {
  type DType = A
  // more stuff
}
并修改
get
定义

def get(size: Int)(implicit ct: ClassTag[B]) = new Array[dtype.DType](size)
但是通过这种方式,您将拥有从
IntType
StringType
等派生的长类型签名。

这将起作用

  def get(size: Int)(implicit tag: ClassTag[DataType]) = new Array[DataType](size)
或者使用等效的上下文绑定

  def get[DType: ClassTag](size: Int) = new Array[DType](size)
您甚至可以用模板
T
替换
DType

数组的
构造函数实际上接受类型为
ClassTag
的隐式参数,因此您需要隐式或显式地提供一个参数

编辑:还值得注意的是,使用
dtype.dtype
将不起作用,因为
dtype
属于
DataType
类型,它没有具体的
dtype
,而只是一个抽象的类型。有趣的是,
dtype.type
可以正常工作,因为在运行时
valdtype:DataType
已经是
IntType

EDIT2:如果你想传播类型,恐怕唯一的方法就是使用类型类

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]
  }
}
这样,您就可以去掉
DType
,而改用type类的类型。您不引入任何样板文件,因为您想定义
IntType
,而且可能还要定义更多类型。 希望这个能解决你的问题:)

编辑3:如果你想保留你的
DType
只需使用

trait DataType[A] {
  type DType = A
  // more stuff
}
并修改
get
定义

def get(size: Int)(implicit ct: ClassTag[B]) = new Array[dtype.DType](size)

但通过这种方式,您将拥有一个从
IntType
StringType
等派生的长类型签名。

densite.get(4)
返回数组[Nothing]。当我执行
dense[IntType.DType].get(4)
时,它会起作用,但这看起来是多余的。当然-
DType
只是一个类型别名,在这种情况下,它是在您定义的每个类中定义的,例如
IntType
。您自己不会引入类型层次结构
IntType.DType
只是在编译时说
Int
的一种奇特方式。更新了答案@marcin_Kosthanks,这很有效。我在某个地方读到过,类型成员应该是首选的,但我想这取决于手头的问题。是的,这很难。更进一步的更新:D我建议阅读猫或Scalaz的资料来了解它@marcin_koss
densed.get(4)
返回数组[Nothing]。当我执行
dense[IntType.DType].get(4)
时,它会起作用,但这看起来是多余的。当然-
DType
只是一个类型别名,在这种情况下,它是在您定义的每个类中定义的,例如
IntType
。您自己不会引入类型层次结构
IntType.DType
只是在编译时说
Int
的一种奇特方式。更新了答案@marcin_Kosthanks,这很有效。我在某个地方读到过,类型成员应该是首选的,但我想这取决于手头的问题。是的,这很难。更进一步的更新:D我建议阅读猫或Scalaz的资料来了解它@马辛科斯