Based on the question asked and answered here, I have a second, more complex one (at least in my opinion). To make reading (and answering) easier, I will, 开发者_StackOverflow中文版however, restate the complete code example here:
Let us begin by defining a set of classes/interfaces:
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> {
}
I now need to define an intermodal graph, i.e. a graph containing PTEdges as well as RoadEdges. In my opinion, I would do this by stating
public class IntermodalGraph implements Graph<Node, Edge> {
}
Here the compiler complaints on Node and Edge, since Node is defined to have two type parameters whereupon one is derived from the second type (here Edge). This means, I would have to state
public class IntermodalGraph implements Graph<Node<Node, Edge>, Edge> {
}
So far, the first type parameter (Node) is ok, but the second one (Edge) fails since edges takes two type parameters again, the first one derived from Node. So, I would write
public class IntermodalGraph implements Graph<Node<Node, Edge>, Edge<Node<Node, Edge>>, Edge> {
}
Now, the second type parameter is ok, but the first one is (obviously) "bad" again.
In the end, I would like to achieve some code like
IntermodalGraph ig = new IntermodalGraph();
ig.add(new PTEdge());
ig.add(new RoadEdge());
Set<Edge> edges = ig.getEdges();
So does anybody have an idea how to achieve this while keeping type safe?
lg, Matthias
Since your classes already specify the generics, you could declare your IntermodalGraph
class as
public class IntermodalGraph<NT extends Node<NT, ET>, ET extends Edge<NT, ET>> implements Graph<NT, ET> {
}
And this should not throw any warnings.
** EDIT **
You can't accomplish what you want, that is having
IntermodalGraph ig = new IntermodalGraph();
ig.add(new PTEdge());
ig.add(new RoadEdge());
Set<Edge> edges = ig.getEdges();
not throw any unchecked
warnings, unless you add @SuppressWarnings("unchecked")
annotations. But, it is still valid Java syntax and will work; the generic NT
will default to Node
and ET
to Edge
As already pointed out by toto, you define a type checkable contract and then proceed to break it -- and the compiler intervenes. A type safe solution is to simply split the contract in two, a weaker and a stricter one: A Graph<N extends Node<?, ?>, E extends Edge<?, ?>>
interface as well as a StrictGraph<N extends Node<N, E>, E extends Edge<N, E>>
interface which extends Graph<N, E>
.
精彩评论