6

クラスのインスタンスが与えられると、明らかにその名前を返すことができます。

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

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

ただし、この方法では、のインスタンスごとに1回、リフレクションを使用しますAClass。代わりに、クラスごとに同じことを1回行うことはできますか?

頭に浮かぶ解決策の1つは、クラス自体ではなく、コンパニオンオブジェクトに混合することです。

4

2 に答える 2

1

あなたはポン引き私の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
于 2010-05-12T13:57:08.880 に答える
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で装飾するだけでなく、コンパニオンメソッドを実装し、クラスごとにコンパニオンオブジェクト(ちなみに同じ名前である必要はありません)を作成する必要があります。

于 2010-05-12T14:44:54.900 に答える