从trait本身将实现trait的类的名称更改为String

时间:2014-07-19 05:37:10

标签: scala reflection

我有一个由大量类实现的特性,我想在运行时使用实现此特征的类的名称,但尽可能集中代码。

具体来说,在我的代码中,我使用标记来表示要在运行时初始化的类。令牌携带配置,并且根据需要通过令牌实例化实际类,并结合运行时信息。为了链接我的应用程序之外的资源,我希望能够访问定义了令牌的类的名称。参见示例:

trait Token[Cls] {
  val className = ???

  // Example generic method depending on final class name
  def printClassName = println(className)
}

case class ClassA(t: ClassAToken, runtimeContext: String) {
  // a bunch of other code
}

object ClassA {
  case class ClassAToken(configParam: String) extends Token[ClassA]
}

所以,我试图实施className。理想情况下,我可以在编译时提取此信息一次。如何保持样板代码不在ClassA范围内?虽然,如果我可以删除type参数并获取在运行时实现Token特征的类的名称,那也很棒。

1 个答案:

答案 0 :(得分:1)

由于类型删除 Cls在运行时不再可用。要在运行时获取信息,您需要使用TypeTag(在您的情况下是ClassTag)。

您的代码可能如下所示:

import scala.reflect._

trait Token[Cls] {
  def className(implicit ct: ClassTag[Cls]) = ct.runtimeClass.getName

  // Example generic method depending on final class name
  def printClassName(implicit ct: ClassTag[Cls]) = println(className)
}

case class ClassA(t: ClassAToken, runtimeContext: String) {
  // a bunch of other code
}

object ClassA {
  case class ClassAToken(configParam: String) extends Token[ClassA]
}

或者如果你可以让Token成为一个类,你可以使用ClassTag上下文边界:

import scala.reflect._

class Token[Cls: ClassTag] {
  def className = classTag[Cls].runtimeClass.getName

  // Example generic method depending on final class name
  def printClassName = println(className)
}

case class ClassA(t: ClassAToken, runtimeContext: String) {
  // a bunch of other code
}

object ClassA {
  case class ClassAToken(configParam: String) extends Token[ClassA]
}

有关TypeTags / ClassTags的更多信息,请参阅Scala: What is a TypeTag and how do I use it?