java - 返回子类时方法的返回类型不兼容

标签 java inheritance subclass extends return-type

我正在尝试定义一种方法来返回签名给出的图上给定顶点的所有邻居

public abstract class GraphClass<V extends Vertex<?>,E extends Edge<V,?>> implements UndirectedGraph<V,E>{
.
.
.
        public ArrayList<V> getNeighbors(V v) {...}
}

我希望从我的 KTree 类中重写这个方法,该类扩展了上面的 GraphClass,如下所示

public class KTree extends GraphClass<KVertex,KEdge> {...
    public ArrayList<KVertex> getNeighbors(KVertex v) {
            return v.getAdjList();
    }
}

这给了我以下错误

Incompatible types. found 'java.ustil.ArrayList>', required 'java.ustil.ArrayList'


KVertex 类还扩展了原始的 Vertex 类,其中找到了 .getAdjList() 方法

public class KVertex extends Vertex<Integer> {...}

 public class Vertex<V>{
        protected ArrayList<Vertex<V>> neighbours = new ArrayList<>();
        ...
        public ArrayList<Vertex<V>> getAdjList(){
            return neighbours;
        }
    }

我在编写此方法时的假设是返回该类型的子类应该仍然是有效的返回类型,因为 KVertex 继承 Vertex 类,并保留 is-a 关系。我该如何正确定义 KVertex 类或 getNeighbours 方法,以便我可以返回 Vertex 的任何子类的列表。谢谢!

最佳答案

主要问题出在Vertex类的方法上

public ArrayList<Vertex<V>> getAdjList()
{
  return neighbours;
}

暗示它将返回一个 ArrayList<Vertex<Integer>>为你的 KVertex类。

但是getNeighbours(V v)想要返回 ArrayList<KVertex>ArrayList<Vertex<Integer>> 不协变所以这不可能发生。 is-a关系在类之间有效,但在类型变量之间无效:a List<KVertex> 不是 List<Vertex<Integer>> .

您的问题的解决方案是传递 Vertex 的真实类型到类(class)本身,例如:

  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();
    }
  }

通过这种方式,您可以生成 getAdjList返回 List扩展您的 Vertex<V> 的类型.

关于java - 返回子类时方法的返回类型不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33456675/

相关文章:

java - 线程安全的java有限状态机(FSM)

c# - 如何获取执行类型的名称?

python - 无法在子初始化器的列表理解中调用父方法,但显式循环有效

java - 在main方法中调用父类(super class)

Java:子类化泛型类

javascript - 如何在 Javascript (ES6) 中正确定义子类构造函数?

java - JRibon - 如何将最小化、最大化、关闭按钮和标题栏放置在 JRibon 顶部?

java - 在查询 firestore 时使用 SnapshotParser 是否是一项昂贵的操作?

C# 转换为基类并使用它的方法

java - Java 中的继承。 2 个子级无法访问彼此的重写方法