问题
I am trying to define a method to return all neighbours of a given vertex on a graph given by the signature
public abstract class GraphClass<V extends Vertex<?>,E extends Edge<V,?>> implements UndirectedGraph<V,E>{
.
.
.
public ArrayList<V> getNeighbors(V v) {...}
}
I wish to override this method from my KTree class which extends the above GraphClass as follows
public class KTree extends GraphClass<KVertex,KEdge> {...
public ArrayList<KVertex> getNeighbors(KVertex v) {
return v.getAdjList();
}
}
Which gives me the following error
Incompatible types. found 'java.ustil.ArrayList>', required 'java.ustil.ArrayList'
The KVertex class also extends the original Vertex class where the .getAdjList()
method is found
public class KVertex extends Vertex<Integer> {...}
public class Vertex<V>{
protected ArrayList<Vertex<V>> neighbours = new ArrayList<>();
...
public ArrayList<Vertex<V>> getAdjList(){
return neighbours;
}
}
My assumption when writing this method was that returning a subclass of that type should still be a valid return type because of KVertex Inheriting Vertex class, and preserving the is-a relationship. How might I properly define the KVertex class or the getNeighbours method so that I could return a list of any subclass of Vertex. Thank You!
回答1:
The main problem resides in the Vertex class the method
public ArrayList<Vertex<V>> getAdjList()
{
return neighbours;
}
implies that it will return a ArrayList<Vertex<Integer>>
for your KVertex
class.
But getNeighbours(V v)
wants to return an ArrayList<KVertex>
which is no covariant with ArrayList<Vertex<Integer>>
so this can't happen. The is-a
relationship is valid between classes, not between type variables: a List<KVertex>
is-not-a List<Vertex<Integer>>
.
A solution to your problem is to pass the real type of the Vertex
to the class itself, eg:
class Vertex<V, R extends Vertex<V, R>>
{
protected List<R> neighbours = new ArrayList<>();
public List<R> getAdjList()
{
return neighbours;
}
}
public abstract class GraphClass<V extends Vertex<?,?>,E extends Edge<V,?>> implements UndirectedGraph<V,E>
{
public abstract List<? extends V> getNeighbors(V v);
}
public class KVertex extends Vertex<Integer, KVertex>
{
}
public class KTree extends GraphClass<KVertex,KEdge>
{
@Override
public List<KVertex> getNeighbors(KVertex v)
{
return v.getAdjList();
}
}
In this way you make the getAdjList
return a List
of the type that extends your Vertex<V>
.
回答2:
Hmmm... I'm not really sure, but maybe this will work...
public class Vertex<V>{
protected ArrayList<Vertex<V>> neighbours = new ArrayList<Vertex<V>>();
...
public ArrayList<Vertex<V>> getAdjList(){
return neighbours;
}
}
来源:https://stackoverflow.com/questions/33456675/incompatible-return-types-for-method-when-returning-subclass