CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    Apr 2011
    Posts
    2

    Use generics to operate on a class and its subclass equally

    Hello,
    I'm a bit new to Java (and OOP in general). I have a set of classes Vertex, Edge, and Graph that I'm trying to use to do some network analysis. These classes work fine.

    I want to create a subclass of Vertex that I'm calling PrVertex, which is nearly identical to Vertex, except that it includes an extra parameter to describe that Vertex's probability. Methods that are used on PrVertex should work exactly the same as they would with Vertex, but PrVertex has one extra method to return the probability of that vertex.

    A Graph is constructed of lists of Edges and Vertexes. I would like to be able to use a Graph object to represent either a list of Vertexes and a list of Edges OR a list of PrVertex-es and a list of Edges. The code using Graph objects simply uses them to pass between methods as a single object. After reading up on generics, I think this is possible, but I can't exactly wrap my mind around it.

    The existing code that I'm using has a lot of statements like this:
    Code:
    ArrayList<Vertex> nodes = new ArrayList<Vertex>(graph.getVertexes());
    where graph is a Graph instance.

    I would like to be able to form a Graph with a list of PrVertex-es, and pass that to the existing code, agnostic of whether the Graph is PrVertex or Vertex. I tried to do this, but it would not compile, as the Graph constructor would not accept lists of type List<PrVertex>.

    This is the code I'm utilizing, copied almost entirely from a tutorial by Lars Vogel
    (http://www.vogella.de/articles/JavaA...a/article.html)

    Code:
    public class Vertex {
    	final private String id;
    	final private String name;
    	
    	
    	public Vertex(String id, String name) {
    		this.id = id;
    		this.name = name;
    	}
    	public String getId() {
    		return id;
    	}
    
    	public String getName() {
    		return name;
    	}	
    }
    Code:
    public class PrVertex extends Vertex{
    	final private Double probability;
    	
    	public PrVertex(String id, String name, Double probability){
    		super(id,name);
    		this.probability = probability;
    	}
    		
    	public Double getProbability(){
    		return probability;
    	}	
    	
    }
    Code:
    public class Graph {
    	private final List<Vertex> vertexes;
    	private final List<Edge> edges;
    
    	public Graph(List<Vertex> vertexes, List<Edge> edges) {
    		this.vertexes = vertexes;
    		this.edges = edges;
    	}
    	
    	public List<Vertex> getVertexes() {
    		return vertexes;
    	}
    
    	public List<Edge> getEdges() {
    		return edges;
    	}
    }

  2. #2
    Join Date
    Apr 2011
    Posts
    2

    Re: Use generics to operate on a class and its subclass equally

    Perhaps a more concise question:
    Is it possible to use generics to modify an existing class, so that invocations of List or ArrayList will implicitly take on either its class or subclass, whichever is passed to it?

    That is, execution of the following code would create a list of type <PrVertex>.

    Code:
    ArrayList<PrVertex> prNodes = new ArrayList<PrVertex>();
    
    Graph graph = new Graph(prNodes,edges);
    
    ArrayList<Vertex> newNodes = new ArrayList<Vertex>(graph.getVertexes());
    where

    Code:
    public class Graph{
    	ArrayList<Vertex> vertexes;
    	ArrayList<Edge> edges;
    
    	public Graph(ArrayList<Vertex> vertexes, ArrayList<Edge> edges){
    		this.vertexes = vertexes;
    		this.edges = edges;
    	}
    
    	public ArrayList<Vertex> getVertexes(){
    		return vertexes;
    	}
    }
    and PrVertex is a subclass of Vertex

  3. #3
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Use generics to operate on a class and its subclass equally

    Quote Originally Posted by thegeniusboy05 View Post
    I would like to be able to form a Graph with a list of PrVertex-es, and pass that to the existing code, agnostic of whether the Graph is PrVertex or Vertex. I tried to do this, but it would not compile, as the Graph constructor would not accept lists of type List<PrVertex>.
    If PrVertex is a subclass of Vertex and you want to pass them around interchangeably, you can only do this via the base class type, Vertex. This means that in the common code, PrVertex objects will look just like Vertex objects and you won't have access to methods specific to PrVertex.

    However, suppose that you could pass either Vertex of PrVertex via some common type declaration - if you want to access methods specific to PrVertex somewhere in that common code, how will you know whether you have a Vertex or a PrVertex object at that point?

    Another way to look at this is to ask where do you want to return the probability of the vertex, and what do you do if the object you have at that point is a Vertex rather than a PrVertex?

    This is a large-scale design problem. You need to separate the code that requires PrVertex-specific methods from the code that uses only Vertex methods. You can then pass only PrVertex objects to the former, and both Vertex and PrVertex objects to the latter via Vertex reference variables.

    Language serves not only to express thought but to make possible thoughts which could not exist without it...
    B. Russell
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

  4. #4
    dlorde is offline Elite Member Power Poster
    Join Date
    Aug 1999
    Location
    UK
    Posts
    10,163

    Re: Use generics to operate on a class and its subclass equally

    Quote Originally Posted by thegeniusboy05 View Post
    Perhaps a more concise question:
    Is it possible to use generics to modify an existing class, so that invocations of List or ArrayList will implicitly take on either its class or subclass, whichever is passed to it?
    Yes, if I understand what you're asking correctly, you can do it like this:
    Code:
    class Graph<T extends Vertex> {  // 'T' is some type that extends Vertex
        ArrayList<T> vertexes;
        ArrayList<Edge> edges;
    
        public Graph(ArrayList<T> vertexes, ArrayList<Edge> edges) {
            this.vertexes = vertexes;
            this.edges = edges;
        }
    
        public ArrayList<T> getVertexes() {
            return vertexes;
        }
    }
    Note that this will not change the underlying type of the object stored or returned. If you pass in a list of PrVertex objects, it will store PrVertex objects and return a list of PrVertex objects - but you can declare the returned list as Vertex objects, hiding the underlying PrVertex type:
    Code:
    ArrayList<PrVertex> prNodes = new ArrayList<PrVertex>();
    
    // Graph that takes PrVertex list        
    Graph<PrVertex> graph = new Graph<PrVertex>(prNodes, edges);
    
    // Extract list of PrVertex
    ArrayList<PrVertex> newPrNodes = new ArrayList<PrVertex>(graph.getVertexes());
    
    // Extract as list of Vertex (still PrVertex objects) 
    ArrayList<Vertex> newNodes = new ArrayList<Vertex>(graph.getVertexes());
    I hope this is the kind of thing you were after.

    Thus the task is not so much to see what no one has yet seen, but to think what no one has yet thought about that which everybody sees...
    E. Schrodinger
    Last edited by dlorde; April 5th, 2011 at 06:27 AM.
    Please use &#91;CODE]...your code here...&#91;/CODE] tags when posting code. If you get an error, please post the full error message and stack trace, if present.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured