Почему манифест недоступен в конструкторе?

Рассмотрим этот код:

class Foo[T : Manifest](val id: String = manifest[T].erasure.getName)

Я в основном хочу сохранить идентификатор в Foo, который часто является просто именем класса.

Подкласс, который не нуждается в специальном идентификаторе, может затем легко использовать значение по умолчанию.

Но это даже не компилируется, сообщение об ошибке:

error: No Manifest available for T.

Есть ли другой подход, который будет работать?

EDIT:

Почему это работает, если манифест недоступен до основного конструктора?

class Foo[T: Manifest](val name: String) { 
  def this() = this(manifest[T].erasure.getName)
}

Ответы

Ответ 1

Когда синтаксический сахар удаляется из этого контекста, он переписывается как:

class Foo[T]
  (val id: String = implicitly[Manifest[T]].erasure.getName)
  (implicit ev$1: Manifest[T]) = ...

Таким образом, доказательства Manifest просто недоступны при определении значения по умолчанию id. Вместо этого я напишу что-то вроде этого:

class Foo[T : Manifest](id0: String = "") {
  val id = if (id0 != "") id0 else manifest[T].erasure.getName
}

В вашем втором подходе (который является отличным решением, кстати!), ожидайте переписывание, похожее на:

class Foo[T](val name: String)(implicit x$1: Manifest[T]) { 
  def this()(implicit ev$2: Manifest[T]) = this(manifest[T].erasure.getName)
}

Итак, да, манифест есть, доступный до вызова manifest[T].erasure