Scala: получение названия класса, в котором смешана черта - PullRequest
6 голосов
/ 12 мая 2010

Учитывая экземпляр класса, мы можем, очевидно, вернуть его имя:

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

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

Но этот способ использует отражение, один раз для каждого экземпляра AClass. Можно ли сделать то же самое по одному разу для каждого класса?

Одно из решений, которое приходит на ум, - это смешивать его с сопутствующими объектами вместо самих классов.

Ответы [ 2 ]

1 голос
/ 12 мая 2010

Я не могу придумать, как это сделать без лишних затрат. Однако вы можете сделать это с сопутствующими объектами и несколькими дополнительными работами:

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, но и реализовать метод-компаньон и написать объект-компаньон (которому, кстати, не нужно иметь одинаковое имя) для каждого класса.

1 голос
/ 12 мая 2010

Вы можете сделать это с помощью шаблона 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
...