【问题标题】:Why is the Manifest not available in the constructor?为什么 Manifest 在构造函数中不可用?
【发布时间】:2011-11-09 19:41:29
【问题描述】:

考虑这段代码:

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

我基本上想在 Foo 中存储一个标识符,通常只是类名。

不需要特殊标识符的子类可以轻松使用默认值。

但这甚至没有编译,错误信息是:

error: No Manifest available for T.

还有其他可行的方法吗?

编辑:

如果清单在主构造函数之前不可用,为什么这会起作用?

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

【问题讨论】:

  • 不是答案,但如果您使用manifest[T] 而不是implicitly[Manifest[T]],您将拥有更简洁的代码。

标签: class scala types constructor manifest


【解决方案1】:

当从上下文绑定中删除语法糖时,它会被重写为:

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

因此,在确定id 的默认值时,Manifest 证据根本不可用。我会写这样的东西:

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之前清单可用的

【讨论】:

  • 但是不会创建一个多余的字段吗?
  • 为了避免多余的字段,请从id0 的定义中删除val 修饰符?
  • Kipton - 确实如此,认为它已经消失了
  • @soc - 通常最好避免使用下划线,这是一个重载符号,除非规范要求。
猜你喜欢
  • 2017-04-09
  • 1970-01-01
  • 2016-02-17
  • 2011-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-18
  • 2017-12-21
相关资源
最近更新 更多