我有一个由大量类实现的特性,我想在运行时使用实现此特征的类的名称,但尽可能集中代码。
具体来说,在我的代码中,我使用标记来表示要在运行时初始化的类。令牌携带配置,并且根据需要通过令牌实例化实际类,并结合运行时信息。为了链接我的应用程序之外的资源,我希望能够访问定义了令牌的类的名称。参见示例:
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
特征的类的名称,那也很棒。
答案 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?