scala 类型标签和类型别名

标签 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]))

第一个比较为 true,第二个为 false。我能以某种方式修复它吗?一般来说,我将有更多“类型”实例用作域模型中的类的构造函数,并且希望迭代这些集合并选择一个匹配的实例。

最佳答案

问题是,当您静态键入 lv 作为 Type 时,您会丢弃有关 Value 类型成员的(静态)信息。如果您让类型被推断(或将 { type Value = Long } 添加到显式类型注释中),那就没问题了。

但是,一旦您创建了具有不同 Value 值的 Type 实例集合,您就会再次运气不佳,因为推断出的类型集合将类似于 List[Type { type Value >: Long with Whatever }],本质上与 List[Type] 相同。感谢类型删除(我并不是在讽刺——类型删除在这里确实做了正确的事情),您将无法使用模式匹配或传统的 Java 反射工具从基于集合的集合中挑选项目。在其 Value 类型成员上。

所以简短的回答是“不要这样做”。您将进入静态类型无法帮助您的领域,并且几乎肯定有更好的方法来构造您的程序。不过,如果您绝对坚持采用这种方法,则可以使用类型标签。以下是一个稍微简化的示例:

scala> import scala.reflect.runtime.universe.{ TypeTag, typeOf }
import scala.reflect.runtime.universe.{TypeTag, typeOf}

scala> trait Foo { type Value; implicit def vTag: TypeTag[Value] }
defined trait Foo

scala> class Bar[V](implicit val vTag: TypeTag[V]) extends Foo { type Value = V }
defined class Bar

scala> val xs = List(new Bar[Int], new Bar[String], new Bar[Symbol])
xs: List[Bar[_ >: Symbol with String with Int]] = ...

scala> xs.filter(_.vTag.tpe =:= typeOf[Symbol])
res0: List[Bar[_ >: Symbol with String with Int]] = List(Bar@68e2cd6f)

但这确实令人不快——我们只是将有关值类型的信息作为运行时值本身传递。新的反射 API 使语法相当清晰,但这并不意味着这是一个好主意。

关于scala 类型标签和类型别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22285837/

相关文章:

c# - C# 中的任意位大小的数据类型

scala - 具有动态条件的 Slick 普通 SQL 查询

scala - 是否有用于Scala的代码混淆工具?

scala - 喷涂框架的生产准备就绪了吗?

scala - 使用 Spark Scala 将 HDFS 文件内容存储在 ArrayBuffer 中

java - 如何判断原始类型是否被转换为 Java 中的对象?

c# - C#中的数据类型

javascript - 为什么 JavaScript 按位或行为异常?

java - 我想在android中获取类的字段名称

Golang使用reflect设置结构体字段