I have super abstract class Node and 50 types of subclasses SubNode.
I have a generic Class <E extends Node> which has a private var List<E> and a method which unfortunately has to accept superclass Node ALWAYS, cannot move it to just E:
public void addSubElement (Node node){
if (node instanceOf E) subElements.add((E)node);
else //Doing extra steps for occasional non-E nodes like discarding them silently without CastException;
}
Any solution (Reflection?) able to compile without warnings, throwing a CastException instead of adding any object due to type erasure??...
I don´t want to have to write same function for any type of subclass:
public void addSubElement (Node node){
if (node instanceOf SubNode1) subElements.add((SubNode1)node);
if (node instanceOf SubNode2) subElements.add((SubNode2)node);
//if (node instanceOf SubNode50....
}
It would be so nice having a method like.
public void addSubElement (Node node){
subElements.add((E)node.autoCastToSubClassOfAbstract("Node")); //Should throw CastException if non-E
}
or
public void addSubElement (Node node){
subElements.add(node.autoCastTo("E")); //Should throw CastException if non-E
}
You have a flaw in your design. Either the signature of the method should be:
or
subElements
should be of typeList<Node>
insteadList<E>
.Let's say your class is
NodeList<E extends Node>
, and then you create an instance:Then the list will only accept instances of
SubNode1
, so you wouldn't be able to doUpdate:
The only workaround that I found is this:
When using generics, there are corner cases where you can't write valid code without suppressing warnings.
The pure OO approach for your problem would be to write on
addSubElement()
method for each type. That would give you one method per type in each type (N*N). You could add the special cases in the respective types.Obviously for any significant number of different types (say more than three), the number of methods quickly explodes and you will find yourself in a situation where you have to cut&paste a lot of code.
Even if you need only to write a few of them and delegate most of the work to a generic
addSubElement(Node)
method, it would still create a technical debt because you'd need to write X methods for each new type.So for your corner case, there is probably no way around
instanceof
and@SuppressWarnings("unchecked")
.[EDIT]
You could define an interface
INode
whichNode
has to implement. Your class could then look like this:This pattern would allow you to either restrict the possible types of nodes which this implementation accepts or use
Node
forN
for something that accepts anything and where you do special handling in the method.The advantage here is that you could get compile time errors when you pass a type to an implementation which can't handle it. But you would still need a cast in the method and to suppress the warning.
If you are forced somehow to have a
then your only option is to use
There is no way to achieve this without getting a warning (which you of course can suppress).
This is fine as long as you are the only one using this method, you can just ignore the warning as long as you make sure to always call it with the correct argument.
EDIT: FINAL ANSWER FROM ALL OTHER ANSWERS:
I was hesitating if accepting titofb answer, beause he is the one who appointed the good way. But I think it is enough targeted on y problem that should acept my own (for very 1st time), for the benefit of others who read it. Thanks to all!
Abstract Node class implements this:
So any Subnode has always an available method which returns his own Type E from definition SubnodeN extends Node<SubNodeX> (SubnodeX = N in Node<E>). That means that we can do that in any node:
And then here it is the magic. This is the default behavior. It warns you if some child was not expected, but you can override this method for any subnode for handling special cases: