I know it makes sense that it is, but it is not. The fact that it is not was easier for me to understand after I learned that all this lovely type-checking information we write all those angle-brackets for is NOT available at runtime -- Java checks these things at compile time, and boils them all down to their most generic form at runtime.
Therefore, as far as the runtime is concerned, you can put any subclass of Node into ArrayList<Node>, and that makes it unsuitable for holding any specific subclass of node.
You can read about having an ArrayList<? extends Node>, which may be the closest thing to what you want. It will not, however, check that only one subclass of node is going into the list declared that way. If you really want to do that, you're going to have to declare one ArrayList for each subtype.
Thanks for your response Ralph, that helped out a lot.
Do you think it would be a better design to just hold an ArrayList of each type of Node in its matching Layer. (i.e. InputLayer has an ArrayList of InputNodes, HiddenLayer has an ArrayList of HiddenNodes, etc. Rather than holding a singular list of type Node at in the Layer class, and trying to sort the issue out with generics.
Joined: May 29, 2005
Well, I think it ought to partially depend on the operations you do with them. If all the operations you are liable to perform on HiddenLayer are specific to Hidden nodes, then that makes sense. On the other hand, if many of the operations in Layer are common to Node, so that there will be significant code that could operate on a generic node without having to know which kind of subclass of Node it is, then an ArrayList of <? extends Node> would allow Layer code to operate on "subclass of Node" without having to either duplicate the code or jury-rig the Layer methods to pass their specific subclass into a method that dealt with the superclass, etc. It really comes down to what kind of collection you are trying to represent; if you're going to have 3 different lists, then is Node and its subclasses really an inheritance relationship?
Well it's hard to say, I am constructing an artificial neural network, so some operations in Layer need to be able to apply to all Node type objects, but some operations are unique to the individual node classes and need to be accessed. If I am only storing an ArrayList<Node> in the super class, it makes it difficult to perform the individual operations, but If I have three ArrayList objects then I will be repeating similar code in lots of places. It's a kind of trade off I suppose, anyway thank you for you input, it has helped a lot.
Joined: May 29, 2005
Keep in mind that if the operations are (or can be) performed by the objects in the list, with parameters passed in from the Layer class, then the methods that do those operations can be defined on the specific Node subclasses and they can be stored in an ArrayList<? extends Node>. Unfortunately I don't know anything about neural networks, but let's say you have some kind of visible component for each node, and under some conditions the layer is going to tell specific elements to blink to get a viewer's attention. Let's say further that the blinking behavior is different for each kind of node. blink() can be defined as an abstract method on Node, overridden on each subclass, and called by Layer without any knowledge of which kind of node is being called.
I suppose another way of putting the question is whether the node collections are each different kinds of objects. Is each kind of object only in one layer? Is it the layers that are different kinds of object?
All of those are domain-specific questions -- the software may or may not be robust under any possibly organization; the question is what is it you're trying to represent and what is the most "natural" way to represent that in software given the tools that you have (in this discussion, OO design).