Question
I have the concept of NodeType
s and Node
s. A NodeType
is a bunch of meta-data which you can create Node
instances from (a lot like the whole Class / Object relationship).
I have various NodeType
implementations and various Node implementations.
In my AbstractNodeType (top level for NodeTypes) I have ab abstract createInstance()
method that will, once implemented by the subclass, creates the correct Node instance:
public abstract class AbstractNodeType {
// ..
public abstract <T extends AbstractNode> T createInstance();
}
In my NodeType
implementations I implement the method like this:
public class ThingType {
// ..
public Thing createInstance() {
return new Thing(/* .. */);
}
}
// FYI
public class Thing extends AbstractNode { /* .. */ }
This is all well and good, but public Thing createInstance()
creates a warning about type safety. Specifically:
Type safety: The return type Thing for createInstance() from the type ThingType needs unchecked conversion to conform to T from the type AbstractNodeType
What am I doing wrong to cause such a warning?
How can I re-factor my code to fix this?
@SuppressWarnings("unchecked")
is not good, I wish to fix this by coding it correctly, not ignoring the problem!
Solution
You can just replace <T extends AbstractNode> T
with AbstractNode
thanks to the magic of covariant returns. Java 5
added support, but it didn't receive the pub it deserved.
OTHER TIPS
Two ways:
(a) Don't use generics. It's probably not necessary in this case. (Although that depends on the code you havn't shown.)
(b) Generify AbstractNodeType as follows:
public abstract class AbstractNodeType<T extends AbstractNode> {
public abstract T createInstance();
}
public class ThingType<Thing> {
public Thing createInstance() {
return new Thing(...);
}
}
Something like that should work:
interface Node{
}
interface NodeType<T extends Node>{
T createInstance();
}
class Thing implements Node{}
class ThingType implements NodeType<Thing>{
public Thing createInstance() {
return new Thing();
}
}
class UberThing extends Thing{}
class UberThingType extends ThingType{
@Override
public UberThing createInstance() {
return new UberThing();
}
}