获取隐含证据选择的运行时类型
Get Runtime Type picked by implicit evidence
假设我有一组字符串转换器,作为类型 class:
import scala.reflect.runtime.universe._
abstract class ToStringConverter[T] {
def convert(value: T): String
}
implicit object IntToStringConverter extends ToStringConverter[Int] {
def convert(value: Int) = value.toString
}
implicit object DoubleStringConverter extends ToStringConverter[Double] {
def convert(value: Double) = value.toString
}
以及使用类型信息选择正确转换器的转换方法:
def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v)
如果我事先有具体的类型,这很好用,例如:
scala> convert[Double](12.2)
res0: String = 12.2
scala> convert[Int](12)
res1: String = 12
是否可以将上面的 convert 方法用于运行时类型,例如下面的类型 't'?
scala> val t = typeOf[Double]
t: reflect.runtime.universe.Type = Double
如果要解析运行时,需要反射,因为隐含是在编译时解析的。像这样的代码应该可以完成工作:
import scala.reflect.runtime.universe._
abstract class ToStringConverterAny {
def convertAny(value: Any): String
}
abstract class ToStringConverter[T] extends ToStringConverterAny {
def convertAny(value: Any): String = convert(value.asInstanceOf[T])
def convert(value: T): String
}
implicit object IntToStringConverter extends ToStringConverter[Int] {
def convert(value: Int) = value.toString
}
implicit object DoubleStringConverter extends ToStringConverter[Double] {
def convert(value: Double) = value.toString
}
val converters: Map[Type, ToStringConverterAny] = Map(
typeOf[Int] -> IntToStringConverter,
typeOf[Double] -> DoubleStringConverter
)
def convert(t: Type, v: Any) = {
converters(t).convertAny(v)
}
def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v)
convert[Double](12.2)
convert[Int](12)
val t = typeOf[Double]
val v: Any = 1.23
convert(t, v)
如果你想自动构建 converters
地图,你也可以为此使用反射,但是枚举派生的 classes 需要令人惊讶的 non-trivial 代码(包括 class装载机 - 当你想到它时,这是可以理解的)。
如果你能使 ToStringConverterAny
密封,在宏中枚举其子class 应该会更容易一些。
假设我有一组字符串转换器,作为类型 class:
import scala.reflect.runtime.universe._
abstract class ToStringConverter[T] {
def convert(value: T): String
}
implicit object IntToStringConverter extends ToStringConverter[Int] {
def convert(value: Int) = value.toString
}
implicit object DoubleStringConverter extends ToStringConverter[Double] {
def convert(value: Double) = value.toString
}
以及使用类型信息选择正确转换器的转换方法:
def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v)
如果我事先有具体的类型,这很好用,例如:
scala> convert[Double](12.2)
res0: String = 12.2
scala> convert[Int](12)
res1: String = 12
是否可以将上面的 convert 方法用于运行时类型,例如下面的类型 't'?
scala> val t = typeOf[Double]
t: reflect.runtime.universe.Type = Double
如果要解析运行时,需要反射,因为隐含是在编译时解析的。像这样的代码应该可以完成工作:
import scala.reflect.runtime.universe._
abstract class ToStringConverterAny {
def convertAny(value: Any): String
}
abstract class ToStringConverter[T] extends ToStringConverterAny {
def convertAny(value: Any): String = convert(value.asInstanceOf[T])
def convert(value: T): String
}
implicit object IntToStringConverter extends ToStringConverter[Int] {
def convert(value: Int) = value.toString
}
implicit object DoubleStringConverter extends ToStringConverter[Double] {
def convert(value: Double) = value.toString
}
val converters: Map[Type, ToStringConverterAny] = Map(
typeOf[Int] -> IntToStringConverter,
typeOf[Double] -> DoubleStringConverter
)
def convert(t: Type, v: Any) = {
converters(t).convertAny(v)
}
def convert[T](v: T)(implicit ev: ToStringConverter[T]): String = ev.convert(v)
convert[Double](12.2)
convert[Int](12)
val t = typeOf[Double]
val v: Any = 1.23
convert(t, v)
如果你想自动构建 converters
地图,你也可以为此使用反射,但是枚举派生的 classes 需要令人惊讶的 non-trivial 代码(包括 class装载机 - 当你想到它时,这是可以理解的)。
如果你能使 ToStringConverterAny
密封,在宏中枚举其子class 应该会更容易一些。