我有一个DSL和一些运行时代码。问题是我在运行时到了某个地方:
val clazz: Class[_ <: java.io.Serializable] = classOf[java.lang.String]
val value: java.io.Serializable = "abc"
我有一个班级
class MyWrapper[T <: java.io.Serializable](val data: T)(implicit m: Manifest[T]) {
override def toString = m.runtimeClass
}
val wrapper = new MyWrapper(value)
问题是我需要通过调用java.lang.String
返回toString
。但我得到java.io.Serializable
。遗憾的是,我无法为每个java.io.Serializable
子类型创建固定模式匹配(这会很疯狂),也无法使用MyWrapper
创建new MyWrapper[String](value)
。我不知道value
的类型,也许它是Serializable
的子类型。
如果我知道值类型等于变量clazz
,是否有某种方法可以在运行时传递类型/清单值?
更新(RégisJean-Gilles的解决方案不起作用)。 REPL测试:
val clazz: Class[_ <: java.io.Serializable] = classOf[java.lang.String]
val value: java.io.Serializable = "abc"
class MyWrapper[T <: java.io.Serializable](val data: T)(implicit m: Manifest[T]) {
override def toString = m.runtimeClass.getName
}
val wrapper = new MyWrapper(value)
//val wrapper = new MyWrapper(value)(ClassManifest.fromClass(clazz).asInstanceOf[ClassTypeManifest[java.io.Serializable]])
//val wrapper = new MyWrapper(value)(ClassManifest.fromClass(clazz))
System.err.println(wrapper.toString)
如果我试图通过明确的显式,我收到了错误:
scala> :load test.scala
Loading test.scala...
clazz: Class[_ <: java.io.Serializable] = class java.lang.String
value: java.io.Serializable = abc
defined class MyWrapper
<console>:10: error: type mismatch;
found : scala.reflect.ClassManifest[_$1] where type _$1 <: java.io.Serializable
(which expands to) scala.reflect.ClassTag[_$1]
required: Manifest[java.io.Serializable]
val wrapper = new MyWrapper(value)(ClassManifest.fromClass(clazz))
^
<console>:8: error: not found: value wrapper
System.err.println(wrapper.toString)
此外,我无法明确表达。
当我尝试编译我的应用程序时出现了更多奇怪的错误 -
[error] found : scala.reflect.ClassManifest[(some other)_0(in method setProperty)]
[error] (which expands to) scala.reflect.ClassTag[(some other)_0(in method setProperty)]
[error] required: Manifest[_0(in method setProperty)]
[error] new Value.Static(default, Context.virtual(element))(ClassManifest.fromClass(elementProperty.typeClass)))
IMHOégisJean-Gilles非常接近解决方案。如何使它与Scala 2.10一起使用?
答案 0 :(得分:2)
如果我理解正确,您使用清单来解决类型擦除问题,但在特定点上您只需要Class[_]
,因此您需要将其转换回清单。正确的吗?
如果是这样,您可以使用ClassManifest.fromClass
,然后将其显式传递为隐式值m
。
val wrapper = new MyWrapper(value)(Manifest.classType(clazz))
你应该把它抽象出来:
object MyWrapper {
def fromRuntimeType[T <: java.io.Serializable]( value: T ): MyWrapper[T] = {
new MyWrapper(value)(Manifest.classType(value.getClass))
}
}
请记住,因为你首先只有Class
个实例,所以你再次受到类型擦除的支配。这意味着如果类(您需要获取清单)是通用的,则ClassManifest.fromClass
返回的清单中不会包含任何类型参数信息。
答案 1 :(得分:0)
岂不
override def toString = data.getClass.getName
已经为你工作了?这会产生java.lang.String
。