recursive java generics between two classes

This is a question similar to the one asked in Possibly recursive Java generics between two classes. However, so far as stated in that other thread, everything worked alright. In my case, I need unfortunately additional classes using the recursive methods.

To be more specific: I want to define a graph class using edges and nodes. Then, I want to derive a street graph from the graph class which is using roads and junctions as edges and nodes. Additionally, I want to derive a public transport graph using railways and stops as edges and nodes. Finally, I want to define a variable holding either a street graph or a public transport graph. This last step is, what I could not achieve so far. So much with words; now let us have the Java code:

public interface Node<NT extends Node<NT, ET>, ET extends Edge<NT, ET>> {
  /* internal datastructures here */
}

public interface Edge<NT extends Node<NT, ET>, ET extends Edge<NT, ET>> {
  /* internal datastructures here */
}

public interface Graph<NT extends Node<NT, ET>, ET extends Edge<NT, ET>> {
  /* internal datastructures here */
}

public class JunctionNode implements Node<JunctionNode, RoadEdge> {
}

public class RoadEdge implements Edge<JunctionNode, RoadEdge> {
}

public class StreetGraph implements Graph<JunctionNode, RoadEdge> {
}

public class PTNode implements Node<PTNode, PTEdge> {
}

public class PTEdge implements Edge<PTNode, PTEdge> {
}

public class PTGraph implements Graph<PTNode, PTEdge> {
}

Now, so far the defitions. What I want to do is something like:

StreetGraph street = new StreetGraph();
PTGraph ptGraph = new PTGraph();
Graph g = street;
...
g = ptGraph;
...

I want, however, to avoid warnings on raw types, etc. So the obvious way would be:

Graph<Node, Edge> g = street;

This is, however, not possible, since Edge is not a valid substitute for ET of Node (which is absolutely clear for me). I would need something like:

Graph<NT = Node<ET>, ET = Edge<NT>> g;

This is (as expected) not valid Java code. Any ideas, how to achieve valid Java code without warnings/errors and type safety?

Any help appreciated.

Thanks, Matthias

Answer

As Paulo already stated I think that wildcard parameters may be what you are looking for.

Suppose your Graph interface has these methods

public interface Graph<NT extends Node<NT, ET>, ET extends Edge<NT, ET>> {
  public NT getNode();
  public ET getEdge();
}

and your StreetGraph implements them this way

public class StreetGraph implements Graph<JunctionNode, RoadEdge> {

    public RoadEdge getEdge()
    {
        return edge;
    }

    public JunctionNode getNode()
    {
        return node;
    }

}

Then you can do the following just fine, all type-safe and compiler-friendly:

    Graph<?, ?> g = new PTGraph();
    g = new StreetGraph();

    Node<?, ?> n = g.getNode();
    Edge<?, ?> e = g.getEdge();

and then work on the Node and Edge interfaces, agnostic of the underlying implementation.

If you need the extra type information, e.g. if you wanted to access methods that are particular to JunctionNode and RoadEdge but not contained in the Node and/or Edge interfaces, then you would work on the more specific StreetGraph instead of a Graph<?, ?>:

StreetGraph sg = new StreetGraph();
JunctionNode jn = sg.getNode();
RoadEdge re = sg.getEdge();

Leave a Reply

Your email address will not be published. Required fields are marked *