Scala: immer den Namen der Klasse das Merkmal gemischt wird in
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.
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