Java – how to get an inner class to inherit the generic type of the enclosing class?
I'm using java 6
Let my inner class use the same generic class as its closed class At present, I have
public class TernarySearchTree < T > {
...
protected class TSTNode < T > {
// index values for accessing relatives array
protected static final int PARENT = 0,LOKID = 1,EQKID = 2,HIKID = 3;
protected char splitchar;
protected TSTNode < T > [] relatives;
private T data;
protected TSTNode(char splitchar,TSTNode < T > parent) {
this.splitchar = splitchar;
relatives = new TSTNode[4];
relatives[PARENT] = parent;
}
}
}
Now I get a warning
If I delete the type parameter from the inner class (i.e. delete < T > from the protected class tstnode < T > line), I get a compilation error on the lines related = new tstnode [4]
How to make everything right?
Solution
You can:
>Delete the < T > type parameter from tstnode (even if it becomes non generic) – it can still access the external < T > Rename the type parameter (say) u in the < T > class tstnode
[UPDATE]
Here are four different ways to rewrite code They all compile. I think you should consider using enummap (see version 4 below)
Version 1: use different named type parameters in inner classes You need to use a list instead of an array
public class TernarySearchTree<T> {
protected class TSTNode<U> {
// index values for accessing relatives array:
protected static final int PARENT = 0,HIKID = 3;
protected char splitchar;
protected List<TSTNode<U>> relatives;
private U data;
protected TSTNode(char splitchar,TSTNode<U> parent) {
this.splitchar = splitchar;
relatives = new ArrayList<TSTNode<U>>();
for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives
relatives.add(null);
}
relatives.set(PARENT,parent);
}
}
private TSTNode<T> node; // When you use it,pass T as U
public TernarySearchTree() {
node = new TSTNode<T>(',',null); // When you use it,pass T as U
}
}
Version 2: inherit t from closed classes
public class TernarySearchTree<T> {
protected class TSTNode {
// index values for accessing relatives array:
protected static final int PARENT = 0,HIKID = 3;
protected char splitchar;
protected List<TSTNode> relatives;
private T data;
protected TSTNode(char splitchar,TSTNode parent) {
this.splitchar = splitchar;
relatives = new ArrayList<TSTNode>();
for (int i = 0; i < HIKID; ++i) { // Allocate 4 slots in relatives
relatives.add(null);
}
relatives.set(PARENT,parent);
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',null);
}
}
Version 3: use maps (not lists)
public class TernarySearchTree<T> {
protected class TSTNode {
// index values for accessing relatives array:
protected static final int PARENT = 0,HIKID = 3;
protected char splitchar;
protected Map<Integer,TSTNode> relatives;
private T data;
protected TSTNode(char splitchar,TSTNode parent) {
this.splitchar = splitchar;
// Create a hash map. No need to pre-allocate!
relatives = new HashMap<Integer,TSTNode>();
relatives.put(PARENT,parent); // set -> put
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',null);
}
}
}
Version 4: defining indexes as enumerations using enunmap (instead of hash mapping)
public class TernarySearchTree<T> {
protected static enum Index {
PARENT,LOKID,EQKID,HIKID;
}
protected class TSTNode {
protected char splitchar;
protected EnumMap<Index,TSTNode parent) {
this.splitchar = splitchar;
// Create an EnumMap.
relatives = new EnumMap<Index,TSTNode>(Index.class);
relatives.put(Index.PARENT,parent);
}
}
private TSTNode node;
public TernarySearchTree() {
node = new TSTNode(',null);
}
}
[Update 2] one thing to remember: use enummap instead of ordinal indexing
