I have the following nested structure involving type parameters and type members:
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())
}
It seems impossible to me gathering the type information on B at runtime because of the way U1 is specified.
Am I wrong? If not, is there a solution with minor changes in the setup?
Thanks to the answer from Kipton Barros I came up with the following setup:
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)
}
The only downside of this approach is the need for instantiation of U.
I would have thought to use a combination of a type refinement and a Manifest. The former allows to surface the abstract type
_Bas a type parameterB, and the latter instructs the Scala compiler to reify the type ofB(edit: the static type from the call context) as a run-time object. Here’s my attempt,It works in the first case, where explicit type parameters are given. The second case correctly fails to compile, since
U1contains aB1type, not aB2type. Similarly for the third case. For some reason, though, the Scala compiler is generating an incorrect manifest in the fourth case, even though the compiler seems to infer typeB1. I don’t know enough to say whether this is a bug, but it’s certainly surprising to me. Can anyone explain why case (4) doesn’t print B1’s Manifest?