I have a class
with a few objects as inner methods.
I also asked this question a while ago and got a good answer, but that leads to fatal errors in servlet containers. Scala cannot consistently generate a TypeTag
when the URLClassLoader
asks for a class.
The project in question is open-source, found here.
The current approach is found here, but it doesn't preserve order. object members are correctly initialised, but in a random order.
Question: How can you collect class members:
module.instance
)
?Update:
val
instead of object
is not an option, for stylistic reasons.getMethods
or getDeclaredFields
is known not to guarantee order. If this is somehow possible, it's likely with Scala reflection.From http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getDeclaredFields():
public Field[] getDeclaredFields() throws SecurityException
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields. The elements in the array returned are not sorted and are not in any particular order. This method returns an array of length 0 if the class or interface declares no fields, or if this Class object represents a primitive type, an array class, or void. See The Java Language Specification, sections 8.2 and 8.3.
(my emphasis). Similar language is explicitly in the documentation for getDeclaredMethods(), but not in that for getDeclaredClasses() (but can IMO be considered implicit there).
So no, you cannot rely on ordering from Java reflection on the JVM; in practice, I have seen the order vary based on the architecture of the running JVM (32- vs. 64-bit).
If you really must initialize the objects in a particular order (why?), you could use a naming convention and sort manually; however, it would probably be better to change the code to be order-independent.
It appears that you may be able to get something from the Scala reflection API:
trait EarlyInit {
val mirror = runtimeMirror(this.getClass.getClassLoader)
val reflection = mirror.reflect(this)
mirror
.classSymbol(this.getClass)
.toType
.members
.sorted /// This method is documented to return members "in declaration order"
.filter(_.isModule)
.foreach(m => reflection.reflectModule(m.asModule).instance)
}
}
See the API docs:
Sorts the symbols included in this scope so that: 1) Symbols appear in the linearization order of their owners. 2) Symbols with the same owner appear in same order of their declarations. 3) Synthetic members (e.g. getters/setters for vals/vars) might appear in arbitrary order.
However, this will not be guaranteed to work in general, particularly for mixed Java/Scala projects (since there really is no way to get members of a Java class in declaration order). Also, be aware that Scala runtime reflection is not thread-safe and generally not considered production ready.
I still feel that you would be better served by modifying your design to be order independent, possibly by encoding the dependencies differently.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With