Scala: получение названия класса черта смешано в

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

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

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

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

Одно решение, которое приходит на ум, состоит в том, чтобы смешаться, оно в компаньона возражает вместо самих классов.

6
задан Alexey Romanov 12 May 2010 в 13:13
поделиться

2 ответа

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

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
ответ дан 17 December 2019 в 20:29
поделиться

Вы можете сделать это с помощью шаблона 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
ответ дан 17 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: