Frage

eine Instanz einer Klasse gegeben, können wir natürlich seinen Namen zurück:

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

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

Aber auf diese Weise verwendet Reflektion, einmal für jede Instanz von AClass. Kann das gleiche einmal für jede Klasse durchgeführt wird, statt?

Eine Lösung, die den Sinn kommt, ist es zu mischen in Begleiter selbst statt Klassen-Objekte.

War es hilfreich?

Lösung

Ich kann mich keinen Weg, es ohne zusätzlichen Aufwand zu tun. Man könnte es mit Begleiter Objekte tun, aber, und ein paar zusätzliche Stücke der Arbeit:

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 {}
}

Und hier sehen wir, dass dies funktioniert:

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

aber es kommt zu eher einem Preis: Sie brauchen nur die Klasse mit Discovery nicht schmücken, sondern auch den Begleiter Methode implementieren und das Begleitobjekt schreiben (die brauchen nicht die gleichen Namen haben, nebenbei bemerkt) für jede Klasse

Andere Tipps

Sie können es tun, mit dem meine lib Muster pimpen. Erstellen eine implizite Umwandlung von AnyRef zu z.B. ClassNameAdder. Aber es ist nicht zu empfehlen, eine solche implizite Konvertierung vom Typ Hierarchie auf dieser Ebene zu tun erstellen.

Wie auch immer hier kommt der Code:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top