【问题标题】:Reify name of class implementing trait as String, from the trait itself从 trait 本身将实现 trait 的类的名称具体化为 String
【发布时间】:2014-07-19 05:37:09
【问题描述】:

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

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

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之外?不过,如果我可以删除类型参数并在运行时获取实现 Token 特征的类的名称,那也很棒。

【问题讨论】:

    标签: scala reflection


    【解决方案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?

    【讨论】:

    • 我只能在将Token 转换为类时才能使其最终起作用,如您的第二个示例所示。我读过关于 TypeTags 和 ClassTags 的文章,但我认为真正让我感到困惑的是,我在代码中使用它的确切方式,它只是不适用于 trait。幸运的是,在这里使用class 没有问题。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-21
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多