A DESCRIPTION OF THE REQUEST : For type parameters that take type parameters, dot access to the inner type parameters would remove the chore of matching up all the parts of more complex type parameters. For example, public interface Digraph<Node,Edge> takes two type parameters. Type parameter lists that involve Digraph (like Subgraph) get complex quickly. public interface Subgraph<Node,Edge,Supergraph extends Digraph<Node,Edge>> extends Digraph<Node,Edge> Using Subgraph requires matching up Node and Edge type specifiers in two spots. Dot access to contained type parameters would let the compiler do the work for us. public interface Subgraph<Supergraph extends Digraph> extends Digraph<Supergraph.Node,Supergraph.Edge> See http://weblogs.java.net/blog/dwalend/archive/2006/05/tilting_at_the_1.html for more details. JUSTIFICATION : People whine about generics way too often. This change won't stop the simpering, but will save one real headache I've encountered with generics. My JDigraph project is exploring general purpose algorithms written in Java. Having dot access to type parameters would be much easier to work with than the current system. Lining up a nested parameter through several related objects is not so bad, but lining up five is really hard. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - I'd like to be able to have access to a type parameter's type parameters within my java code, instead of having to have long lists of repetitive type parameters. For example, things like public interface Subgraph<Supergraph extends Digraph> extends Digraph<Supergraph.Node,Supergraph.Edge> { public Supergraph.Edge getEdge(Supergraph.Node fromNode,Supergraph.Node toNode); } ACTUAL - instead of giving me the syntax error i deserve, bad things happen inside javac: An exception has occurred in the compiler (1.5.0_06). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you. java.lang.NullPointerException at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:1799) at com.sun.tools.javac.comp.Attr.selectSym(Attr.java:1837) at com.sun.tools.javac.comp.Attr.visitSelect(Attr.java:1724) at com.sun.tools.javac.tree.Tree$Select.accept(Tree.java:987) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:275) at com.sun.tools.javac.comp.Attr.attribType(Attr.java:303) at com.sun.tools.javac.comp.Attr.attribTypes(Attr.java:346) at com.sun.tools.javac.comp.Attr.visitTypeApply(Attr.java:2237) at com.sun.tools.javac.tree.Tree$TypeApply.accept(Tree.java:1058) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:275) at com.sun.tools.javac.comp.Attr.attribType(Attr.java:303) at com.sun.tools.javac.comp.Attr.attribBase(Attr.java:376) at com.sun.tools.javac.comp.MemberEnter.complete(MemberEnter.java:817) at com.sun.tools.javac.code.Symbol.complete(Symbol.java:355) at com.sun.tools.javac.code.Symbol$ClassSymbol.complete(Symbol.java:612) at com.sun.tools.javac.code.Symbol$ClassSymbol.flags(Symbol.java:550) at com.sun.tools.javac.comp.Resolve.isAccessible(Resolve.java:118) ---------- BEGIN SOURCE ---------- package net.walend.digraph; import java.util.Iterator; import java.util.Set; import net.walend.collection.HasState; import net.walend.collection.Bag; import net.walend.collection.HasState; /** Digraph is an interface for representing directed graphs of nodes linked by zero or one edge. Each node and edge must be a unique Object in the digraph. Reusing edges and nodes may produce unpredictable results. <p> By default, this digraph uses equals() as the method to determine identity. <p> One could create a subclass of Digraph that will work with zero or more edges by extending this interface. I have not done that. <p> Direct implementations of Digraph should have a single constructor that takes a Digraph as a parameter. @author @dwalend@ @since 20010612 */ public interface Digraph<Node,Edge> { public int nodeCount(); public int edgeCount(); public boolean isEmpty(); public boolean containsNode(Object node); /** Returns true if the digraph contains any edge from fromNode to toNode @throws NodeMissingException if either node is missing from the digraph. */ public boolean containsEdge(Object fromNode,Object toNode) throws NodeMissingException; /** @throws NodeMissingException if node is not in the digraph. */ public int countInboundEdges(Node node) throws NodeMissingException; /** @throws NodeMissingException if node is not in the digraph. */ public int countOutboundEdges(Node node) throws NodeMissingException; /** Returns the set of nodes that can reach this node by crossing one edge. @throws NodeMissingException if node is not in the digraph. */ public Set<Node> getFromNodes(Node node) throws NodeMissingException; /** Returns the set of nodes that can be reached from this node by crossing one edge. @throws NodeMissingException if node is not in the digraph. */ public Set<Node> getToNodes(Node node) throws NodeMissingException; /** Implementations should explicitly state how they interpret nodeIterator()'s remove method. It should either throw an UnsupportedOperationException or cause a hidden side effects of removing edges. */ public Iterator<Node> nodeIterator(); public Set<Node> getNodes(); /** Returns true if this Digraph has no edges. */ public boolean isEdgeFree(); public boolean containsNodes(Set<?> nodes); /** Returns true if edge links fromNode to toNode @throws NodeMissingException if either node is missing from the digraph. */ public boolean containsEdge(Object fromNode,Object toNode,Object edge) throws NodeMissingException; public Bag<Edge> getEdges(); /** Returns the empty set if node has no inbound edges. @throws NodeMissingException if node is not in the digraph. */ public Bag<Edge> getInboundEdges(Node node) throws NodeMissingException; /** Returns the empty set if node has no outbound edges. @throws NodeMissingException if node is not in the digraph. */ public Bag<Edge> getOutboundEdges(Node node) throws NodeMissingException; /** Returns null if no edge links fromNode to toNode @throws NodeMissingException if either node is missing from the digraph. */ public Edge getEdge(Node fromNode, Node toNode) throws NodeMissingException; /** Returns true if digraph is a subgraph of this Digraph. */ public boolean containsDigraph(Digraph<?,?> digraph); /** Returns true if digraph is the same as this; that is, if this.containsDigraph(digraph) and digraph.containsDigraph(this). */ public boolean sameDigraphAs(Digraph<?,?> digraph); } /*@license@*/ ---- package net.walend.subgraph; import net.walend.digraph.Digraph; /** Subgraph is an interface for representing a Digraph that is a subset of another Digraph. @author @dwalend@ @since alpha-0-8 */ //public interface Subgraph<Node,Edge,Supergraph extends Digraph<Node,Edge>> // extends Digraph<Node,Edge> public interface Subgraph<Supergraph extends Digraph> extends Digraph<Supergraph.Node,Supergraph.Edge> { /** Returns true if this subgraph is still a subgraph of its supergraph */ public boolean valid(); /** Returns the digraph that this Subgraph is built on. */ public Supergraph getSupergraph(); } /*@license@*/package net.walend.subgraph; import net.walend.digraph.Digraph; /** Subgraph is an interface for representing a Digraph that is a subset of another Digraph. @author @dwalend@ @since alpha-0-8 */ //public interface Subgraph<Node,Edge,Supergraph extends Digraph<Node,Edge>> // extends Digraph<Node,Edge> public interface Subgraph<Supergraph extends Digraph> extends Digraph<Supergraph.Node,Supergraph.Edge> { /** Returns true if this subgraph is still a subgraph of its supergraph */ public boolean valid(); /** Returns the digraph that this Subgraph is built on. */ public Supergraph getSupergraph(); } /*@license@*/ ---- package net.walend.digraph; import java.io.Serializable; /** @author @dwalend@ @since 20010620 */ public class NodeMissingException { private static final long serialVersionUID = 0L; private Object missingNode; public static final String DEFAULT = " is not in the Digraph"; public NodeMissingException(Object node) { super(node.toString()+DEFAULT); missingNode = node; } public NodeMissingException(String message,Object node) { super(message+": "+node.toString()); missingNode = node; } public NodeMissingException(Throwable nester,Object node) { super(node.toString()+DEFAULT,nester); missingNode = node; } public NodeMissingException(String message, Throwable nester,Object node) { super(message+": "+node.toString(), nester); missingNode = node; } public Object getNode() { return missingNode; } } /* @license@ */ ---------- END SOURCE ----------
|