从类型参数和类型成员中收集类型信息

时间:2011-10-16 11:25:41

标签: scala

我有以下嵌套结构,涉及类型参数和类型成员:

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.

2 个答案:

答案 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的清单?