有没有办法在运行时发现在外部对象中声明的对象? Java Class
方法getClasses
和getDeclaredClasses
都返回空数组。
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 */ }
}
}
答案 0 :(得分: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)
答案 1 :(得分:1)
刚刚根据自己的需要重新实现它(Riak standalone)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 _ =>
}
}
}