我有以下嵌套结构,涉及类型参数和类型成员:
trait B
trait B1 extends B
trait U {
type _B <: B
}
type U1 = U {
type _B = B1
}
class Q[_U <: U] {
override def toString() : String = {
// print out type information on B here...
}
}
def test() {
val q = new Q[U1]()
println(q.toString())
}
由于指定了U1的方式,我似乎无法在运行时收集B上的类型信息。
我错了吗?如果没有,是否有一个解决方案,在设置中有微小的变化?
感谢Kipton Barros的回答,我想出了以下设置:
trait B
trait B1 extends B
trait B2 extends B
trait U {
type _B <: B
implicit val mfB : Manifest[_B]
}
class U1 extends U {
type _B = B1
val mfB : Manifest[_B] = implicitly
}
class U2 extends U {
type _B = B2
val mfB : Manifest[_B] = implicitly
}
class Q[_U <: U](u : _U) {
override def toString() : String = {
"B: " + u.mfB.erasure.getName()
}
}
def test() {
println(new Q(new U1) toString)
println(new Q(new U2) toString)
}
这种方法的唯一缺点是需要实例化U.
答案 0 :(得分:2)
只是为了澄清一个误解:Manifest
没有携带类型参数的运行时类型。它从调用站点的上下文中携带静态类型,从中调用需要清单的方法或构造函数。
scala> def foo[A: Manifest](a: A) = (manifest[A].erasure, a.asInstanceOf[AnyRef].getClass)
foo: [A](a: A)(implicit evidence$1: Manifest[A])(java.lang.Class[_], java.lang.Class[_])
scala> foo("")
res1: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.String,class java.lang.String)
scala> foo[AnyRef]("")
res2: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.Object,class java.lang.String)
scala> val a: Any = ""
a: Any = ""
scala> foo(a)
res3: (java.lang.Class[_], java.lang.Class[_]) = (class java.lang.Object,class java.lang.String)
答案 1 :(得分:0)
我原本想要使用类型细化和 Manifest 的组合。前者允许将抽象类型_B
表示为类型参数B
,后者指示Scala编译器重新定义B
的类型( edit :来自调用上下文的静态类型)作为运行时对象。这是我的尝试,
trait B
trait B1 extends B
trait B2 extends B
trait U { type _B <: B }
class U1 extends U { type _B = B1 }
class Q[B: Manifest, _U <: U { type _B = B}](u: U) {
override def toString() : String = {
implicitly[Manifest[B]].toString // Manifest[B] was an implicit parameter to Q
}
}
// Four tests:
println(new Q[B1, U1](new U1) toString) // (1) prints "$line1.$read$$iw$$iw$B1"
// println(new Q[B2, U1](new U1) toString) // (2) correctly fails to compile
// println(new Q[Nothing, U1](new U1) toString)// (3) correctly fails to compile
println(new Q(new U1) toString) // (4) prints "Nothing" (why not B1?)
它适用于第一种情况,其中给出了显式类型参数。第二种情况正确无法编译,因为U1
包含B1
类型,而不是B2
类型。同样适用于第三种情况。但是,出于某种原因,Scala编译器在第四种情况下生成了不正确的清单,即使编译器似乎推断类型B1
。我不知道这是不是一个错误,但这对我来说当然是令人惊讶的。 谁能解释为什么案例(4)不能打印B1的清单?