接口中摘要classreturn

Abstract class return in interface

首先,java 很新,很抱歉,如果这是一个简单的问题。

我实现了一个抽象 class 和两个扩展它的 class。

public abstract class Lado{
//body
}

和另外两个 class 以这种形式为例

public class Arista extends Lado
{ //body
}

所以,没问题,现在我有一个这样定义的接口。

public interface Grafo
{  //body
   public List<Lado> lados();
   //more body
}

你看到界面了吗return是class拉多的列表, 但在我的实现中,我需要 return class Arista 的列表或第二个 class (在接口的另一个实现上)

在我必须用于接口实现的代码库中有这样的 lados() 实现

    public List<Lado> lados() {
        return lados;
    }

在我的代码中定义了拉多斯

   private List<Arista> lados;

并初始化

  lados = new LinkedList<Arista>();

现在当然 return 给出了一个错误

GrafoNoDirigido.java:141: error: incompatible types
    return lados;
           ^
   required: List<Lado>
   found:    List<Arista>
1 error

我似乎无法找到如何在不修改给我的基本代码的情况下解决这个问题(我重复不能更改它)。我知道我无法实例化抽象 class 对象,并且抽象 class 实现具有抽象 class 没有的值和函数。

我也不能使用覆盖,原因与我无法在我的实现中更改函数签名的原因相同。

非常感谢你的帮助,谢谢。

如果有任何奇怪的地方,请告诉我。

--------------------编辑-------- 拉多文摘 class.

public abstract class Lado
{
   private String id;
   private double peso;

   public Lado(String id, double peso) {
      this.id = id;
      this.peso = peso;
   }

   public String getId() {
      return id;
   }

   public double getPeso() {
        return peso;
   }

   public abstract String toString();

 }

阿里斯塔潜艇class

public class Arista extends Lado
{
   private Vertice u;
   private Vertice v;

   public Arista(String id, double peso, Vertice u, Vertice v){
      super(id , peso);
      this.u = u;
      this.v = v;
   }

   public Vertice getExtremo1() {
     return u;
   }

   public Vertice getExtremo2() {
     return v;
   }


   public String toString() {
     String s = "string";
     return s;
   }

}

然后如果我 return a List<Lado> 如果你尝试做 getExtremo1() 它确实在编译时找到符号(Lado class 上不存在),试过将输出列表转换为 List<Arista> 但它也没有正常工作。

因为classArtista也是Ladoclass,你的初始化应该是

List<Lado> lados = new LinkedList<>();
:
lados.add(new Artista (..));
:
return lados;

尝试将界面更改为:

public 列表 lados();

public List<? extends Lado> lados();

-- 或--

您可以走另一条路,让列表成为带有子实例的父类型:

private List<Lado> lados;

@Override
public List<Lado> lados() {
    // Type of lados is List<Lado>, but we will fill it up with Arista instances...
    lados = new LinkedList<Lados>();
    lados.add(new Arista());
    // if Arista has methods that follow the with setter stereotype, ie: public Arista withId(int id) { this.setId(id); return this; } you can in-line create them:
    lados.add(new Arista()
              .withId(id)
              .withName(name)
    );
    Arista arista = new Arista();
    lados.add(arista);
    ...
    return lados;
}

希望对您有所帮助!

问题是 Java 对枚举的 "variance" 没有很好的支持(不,这不是一个简单的问题)。看这里,在 "The Workaround" 下寻找解决方案:https://schneide.wordpress.com/tag/upcast/

所以这些是您的限制条件:

  • 您无法更改 lados() 方法 return 类型 (List<Lado>)。
  • 您希望自己的领域属于 List<Arista>

1.复制数组

public List<Lado> lados() {
    return new ArrayList<>(lados);
}

2。将其包装为不可修改的列表*

public List<Lado> lados() {
    return Collections.unmodifiableList(lados);
}

3。类型擦除,千万不要,这样不安全

在 return 编辑它之前擦除您的字段的泛型。不安全,因为如果有人将扩展 Lado 但不是 Arista 的对象添加到该列表,您将拥有 HeapPolution.

@SuppressWarnings("unchecked")
public List<Lado> lados() {
    return (List)lados;
}

如果您不能更改方法 return 类型或变量声明,您可以 return 一个副本:

public List<Lado> lados() {
    return new LinkedList<Lado>(lados);
}

或者您可以 return 包装器:

public List<Lado> lados() {
    return java.util.Collections.unmodifiableList(lados);
}