3 ms·
Seems to me this is approaching this totally the wrong way. First off, the current implementation is just looping through all the methods of the implementing cl
by jtmarmon 9y ago
Seems to me this is approaching this totally the wrong way. First off, the current implementation is just looping through all the methods of the implementing class and the first one that matches a Node or [Node] return type is supposedly its children? That seems extremely brittle.
The fact that you have 100 classes implementing this is a good sign you should turn the design on its head. Why not just have a single tree structure built using generics?
edit: also I would point out that you're not really making reflection any faster, just your code
- dragandj 9y agoOn top of that, he acknowledges that there is a much, much simpler solution, known from the dawn of Java, and this is to have a polymorphic children() method. But that would (gasp!) require adding those implementations. Which is tedious (it is not with a bit of inheritance or some other technique but ok). OK, so, it requires a bit of work. But those methods would take a few (or a dozen) nanoseconds to dispatch; you can't go faster than that. What's the alternative? To build your brittle infrastructure? Hmmm, I must be missing something...
- SOLAR_FIELDS 9y agoThis is assuming you have full control over all the implementations. I see this frequently in large Java and Scala code bases in enterprise, you have a generic library you built awhile back and now has all sorts of users in all different places that you may not even have source code access to, only jar access though Nexus or Artifactory. Then you need to do some operation like OP notes but you can't expect everyone to commit your code immediately or even at all. Thus OP is left with only reasonable solution detailed.
- dtech 9y agoSo your complaint is that it is hard for users if you make a breaking change in your library, big surprise. This is why breaking changes in libraries should only be done with utmost consideration, preferably after first deprecating the usage. And if you make a breaking change to the interface, you better be damn well breaking it at compile time and not hiding it with reflection shenanigans. In the example of the OP, it's easy to think of an example that would totally be broken by the author's reflection approach, while the user has no warning at compile time and no reasonable way of knowing that what he's doing isn't allowed: class MyWeirdNode extends Node { private final int i = 1; public IntNode asIntNode() { return new IntNode(i) } }
- eecc 9y agoThat's where client provided implicit converters in Scala are actually useful magic
- norswap 9y agoI think you're confused about the "heterogeneous tree" parts. All implementation of Node have different children, held in different fields with different names, and varying in numbers. This can't be simplified by inheritance, you need to write an implementation per class.
- flukus 9y ago> The fact that you have 100 classes implementing this is a good sign you should turn the design on its head. Why not just have a single tree structure built using generics? Does anyone know why gui toolkits never do this? Every one seems to follow an OO model where each widget owns it's own children. Even in GTK they hacked in an OO system to do it instead of having a separate tree.
- Sophistifunk 9y agoBecause almost every GUI component is responsible for sizing and positioning its own children. A separate tree might be useful for some other optimisations I can't think of, but it would definitely be a pain for components, even those with a fixed number of children (as opposed to "container" components).
- eecc 9y agoBecause GUIs handle data providers and you have to provide your own adapters to those (so it's even MORE boilerplate)
- norswap 9y agoI'm not seeing how I can use some generic tree class without adding code for each Node subclass, which is exactly what I'm trying to avoid. At the least, I'd have to populate the children list of that class (which is more or less what children() would have done). The identity of each child (what it represents), such as "condition of a while statement" or "body of the else part of an if statement" must be preserved. Also, the issue with methods really isn't, because these classes are really POJOs. Getters and methods inherited from Object is pretty much all they have, so I'm not worried about accidentally capturing a method that is not a getter. And well, this make reflection calls faster by replacing them (probably) with the equivalent plain code.