scala类型标记和类型别名

时间:2014-03-09 17:58:03

标签: scala reflection types alias

如果我在类中有类型别名定义,我可以在运行时将其与静态已知类型或其他类型别名进行比较吗?考虑:

type ConsArguments = (Option[Long], String, Option[String], Iterable[Input])
trait Type {
    val name :String
    type Value
    def apply(id :Option[Long], name :String, label :Option[String], inputs :Iterable[Input]=Iterable()) :Statistic
}
class BaseType[V :TypeTag](val name :String, constructor :((ConsArguments)) => Statistic {type Value=V}) extends Type{
    type Value = V
    def apply(id :Option[Long], name :String, label :Option[String], inputs :Iterable[Input]=Iterable()) :Statistic{type Value=V} =
        constructor((id, name, label, SortedSet[Input]()(Input.nameOrdering)++inputs))
}
val LongValued = new BaseType[Long]("long", (LongStatistic.apply _).tupled)
val lv :Type = LongValued
println("type of LongValued: "+universe.typeOf[LongValued.Value]+" is Long? "+(universe.typeOf[LongValued.Value]=:=universe.typeOf[Long]))
println("type of lv: "+universe.typeOf[lv.Value]+" is Long? "+(universe.typeOf[lv.Value]=:=universe.typeOf[Long]))

第一个比较是真的,第二个是假的。我可以以某种方式解决它吗?通常,我会有更多的“Type”实例作为我的域模型中的类的构造函数,并希望迭代这些类的集合并选择匹配的。

2 个答案:

答案 0 :(得分:3)

问题在于,当您静态键入lvType时,会丢弃有关Value类型成员的(静态)信息。如果你推断出类型(或者将{ type Value = Long }添加到显式类型注释中),你会没事的。

一旦你为Type创建了Value的不同值的实例集合,你就会再次失去运气,因为集合的推断类型将类似于{ {1}},基本上与List[Type { type Value >: Long with Whatever }]相同。由于类型擦除(我不是讽刺型擦除在这里做的正确),你将无法使用模式匹配或传统的Java反射工具从集合中挑选项目他们的List[Type]类型成员。

所以简短的回答是“不要这样做”。你将进入一个静态类型无法帮助你的土地,几乎可以肯定有一种更好的方法来构建你的程序。但是,如果你绝对坚持坚持这种方法,你可以使用类型标签。以下是一个略微简化的示例:

Value

这真的很不愉快,但我们只是将有关值类型的信息作为运行时值本身传递。新的反射API在语法上使它相当干净,但这并不意味着它是个好主意。

答案 1 :(得分:2)

好的,我明白了。变化非常简单:

type ConsArguments = (Option[Long], String, Option[String], Iterable[Input])
trait Type {
    val name :String
    type Value
    val tpe :universe.Type
    def apply(id :Option[Long], name :String, label :Option[String], inputs :Iterable[Input]=Iterable()) :Statistic
}
class BaseType[V :TypeTag](val name :String, constructor :((ConsArguments)) => Statistic {type Value=V}) extends Type{
    type Value = V
    val tpe = typeOf[V]
    def apply(id :Option[Long], name :String, label :Option[String], inputs :Iterable[Input]=Iterable()) :Statistic{type Value=V} =
        constructor((id, name, label, SortedSet[Input]()(Input.nameOrdering)++inputs))
}
val LongValued = new BaseType[Long]("long", (LongStatistic.apply _).tupled)
val lv :Type = LongValued
println("type of lv: "+lv.tpe+" is Long? "+(lv.tpe=:=universe.typeOf[Long]))

但是,在代码中包含double(type ...和val _:Type)声明仍然有点烦人。