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