Scala:得到特质混合的类的名称

时间:2010-05-12 13:13:51

标签: scala traits

给定一个类的实例,我们显然可以返回它的名字:

trait MixedInClassDiscovery {
  val className = this.getClass.getName
}

class AClass extends MixedInClassDiscovery {
  ...
  this.className // returns "AClass"
  ...
}

但这种方式使用反射,对AClass的每个实例都使用一次。可以为每个班级做一次吗?

我想到的一个解决方案是将它混合到伴随对象而不是类本身。

2 个答案:

答案 0 :(得分:1)

你可以使用pimp my lib模式。创建从AnyRef到例如ClassNameAdder的隐式转换scala> class ClassNameAdder(ref: AnyRef) { def className = ref.getClass.getName } defined class ClassNameAdder scala> implicit def anyref2classnameadder(ref: AnyRef) = new ClassNameAdder(ref: AnyRef) anyref2classnameadder: (ref: AnyRef)ClassNameAdder scala> "foo".className res6: java.lang.String = java.lang.String scala> new Object().className res7: java.lang.String = java.lang.Object scala> List(1,2,3).className res8: java.lang.String = scala.collection.immutable.$colon$colon scala> class MyClass defined class MyClass scala> val myClass = new MyClass myClass: MyClass = MyClass@1398044 scala> myClass.className res9: java.lang.String = MyClass 。但是不建议在类型层次结构的这个级别创建这样的隐式转换。

无论如何这里是代码:

{{1}}

答案 1 :(得分:1)

我想不出有任何方法可以做到这一点,没有额外的开销。但是,您可以使用伴随对象,以及一些额外的工作:

object Example {
  trait Discovery {
    def companion: Discovered
    def className: String = companion.className
  }
  trait Discovered extends Discovery {
    override lazy val className = {
      println("Getting class name!")  // To see how many times we're called
      this.getClass.getSuperclass.getName
    }
  }
  class Test extends Discovery {
    def companion = Test
  }
  object Test extends Test with Discovered {}
}

在这里我们看到这有效:

scala> val a = new Example.Test
a: Example.Test = Example$Test@17e4c97

scala> val b = a.className
Getting class name!
b: String = Example$Test

scala> val c = a.className
c: String = Example$Test

但它付出相当代价:您不仅需要使用Discovery装饰类,还需要实现伴随方法并为每个类编写伴随对象(不一定要使用相同的名称)。