如果我在类中有类型别名定义,我可以在运行时将其与静态已知类型或其他类型别名进行比较吗?考虑:
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”实例作为我的域模型中的类的构造函数,并希望迭代这些类的集合并选择匹配的。
答案 0 :(得分:3)
问题在于,当您静态键入lv
为Type
时,会丢弃有关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)声明仍然有点烦人。