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.Child1and 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

刚刚根据我自己的需要重新实现了它(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 回答
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)

第二次尝试:

通过将子对象包装在实例中,可以通过反射检索它们,而无需单独注册它们。但是,有一些开销:

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 回答