5

外部オブジェクト内で宣言されたオブジェクトを実行時に検出する方法はありますか? JavaClassメソッドgetClassesgetDeclaredClasses両方が空の配列を返します。

object Parent {
    object Child1
    object Child2
}

println("Children of Parent:")
println("   getClasses found %d".format(Parent.getClass.getClasses.size))
println("   getDeclaredClasses found %d".format(Parent.getClass.getDeclaredClasses.size))

出力は次のとおりです。

Children of Parent:
  getClasses found 0
  getDeclaredClasses found 0

編集:私は、子供たちに自分自身を親に登録させることを検討しました:

object Parent {
    val children = new collection.mutable.ListBuffer[AnyRef]
    object Child1 { Parent.children += this }
    object Child2 { Parent.children += this }
}

println("(1) Parent.children size: %d".format(Parent.children.size))
Parent.Child1
Parent.Child2
println("(2) Parent.children size: %d".format(Parent.children.size))

(これは見苦しく見えますが、クリエイティブなサブクラス化と暗黙のパラメーターでこれらの詳細を隠すことができるので、実際には問題ありません。)

このアプローチの問題は、各型が参照されるまで静的初期化子が呼び出されないことです (したがって、Parent.Child1およびの呼び出しParent.Child2)。これにより、目的が無効になります。出力は次のとおりです。

(1) Parent.children size: 0
(2) Parent.children size: 2

編集 2:データがそこにあることは知っています! 内部オブジェクトは次を使用してリストされますscalap Parent

object Parent extends java.lang.Object with scala.ScalaObject {
  def this() = { /* compiled code */ }
  object Child1 extends java.lang.Object with scala.ScalaObject {
    def this() = { /* compiled code */ }
  }
  object Child2 extends java.lang.Object with scala.ScalaObject {
    def this() = { /* compiled code */ }
  }
}
4

2 に答える 2

1

内部オブジェクトを登録しても問題ない場合は、より単純なアプローチを検討してみませんか。

object Parent {
  object Child1 
  object Child2 
  val children = List( Child1, Child2 )
}

scala> Parent.children
res: List[ScalaObject] = List(Parent$Child1$@7493931b, Parent$Child2$@49f0d68)

2 回目の試行:

子オブジェクトをインスタンスにラップすることで、個別に登録しなくても、リフレクションによって子オブジェクトを取得できます。ただし、いくつかのオーバーヘッドがあります。

trait HasChildren {
  val children: AnyRef
}

object Parent extends HasChildren {
  val children = new {
    object Child1
    object Child2
  }
}

scala> Parent.children.getClass.getDeclaredFields
res: Array[java.lang.reflect.Field] = 
  Array(private volatile Parent$$anon$1$Child1$ Parent$$anon$1.Child1$module,
  private volatile Parent$$anon$1$Child2$ Parent$$anon$1.Child2$module)
于 2011-08-03T20:42:16.577 に答える
1

私自身のニーズ (Riak スタンドアロン) のために再実装したばかりの Lift (MetaRecord.scala で見つけます) は、次のようにします (私の場合は単純化されています)。

  private def isField(m: Method) = classOf[RiakFieldWrapper[A, AnyRef]].isAssignableFrom(m.getReturnType)

  case class FieldHolder(name: String, method: Method, field: RiakFieldWrapper[A, AnyRef])

  def introspect(rec: BucketWrapper[A], methods: Array[Method]): Unit = {
    for (v <- methods if isField(v)) {
      v.invoke(rec) match {
    case rfw: RiakFieldWrapper[A, AnyRef] => tArray += FieldHolder(rfw.keyName, v, rfw)
    case _ =>
      }
    }
  }
于 2011-11-30T21:32:43.397 に答える