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