tags:

views:

197

answers:

3

I have the concept of NodeTypes and Nodes. 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!

+2  A: 

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.

Hank Gay
Holy crap that's cool. You're right, it really doesn't receive the pub it derserves!
SCdF
Yeah, it's the only worthwhile thing I got out of that stupid SCJP book.
Hank Gay
+1  A: 

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();
 }
}
jrudolph
+1  A: 

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(...);
  }
}
UlfJack