Сбор информации о типе из параметров типа и членов типа - PullRequest
2 голосов
/ 16 октября 2011

У меня есть следующая вложенная структура, включающая параметры типа и члены типа:

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())
}

Мне кажется невозможным собирать информацию о типе B во время выполнения из-за способа указания U1.

Я не прав? Если нет, есть ли решение с небольшими изменениями в настройке?

Благодаря ответу Киптона Барроса я придумал следующую настройку:

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 ]

2 голосов
/ 16 октября 2011

Просто чтобы прояснить ошибочное представление: 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)
0 голосов
/ 16 октября 2011

Я бы подумал использовать комбинацию уточнения типа и Манифест .Первый позволяет отображать абстрактный тип _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) не печатается Манифест В1?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...