2015-05-03 180 views
0

首先,在Java中很漂亮,如果它是一個簡單的問題,抱歉。抽象類返回接口

我已經實現了一個抽象類和兩個擴展它的類。

public abstract class Lado{ 
//body 
} 

和兩個其它類這種形式例如

public class Arista extends Lado 
{ //body 
} 

這樣,也沒有問題,現在我有這樣定義的接口。

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

有你看到的界面返回類拉多, 的名單,但在我執行我需要返回類阿里斯塔的列表或第二類(在界面的另一種實現方式)

在我所要使用的接口實現代碼庫有lados的)這樣

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

與lados在我的代碼定義如下

實現(
private List<Arista> lados; 

和初始化

lados = new LinkedList<Arista>(); 

現在當然回報提供了一個錯誤

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

我似乎無法找到如何解決這個問題,而無需修改給了我基本的代碼(我重複不能改變它)。我知道我不能實例化一個抽象類對象,抽象類實現具有抽象類不支持的值和函數。

另外我不能使用覆蓋的原因,我不能改變我的功能簽名在我的實現。

我會感謝您的幫助,謝謝。

如果有什麼奇怪的東西,請讓我知道。

--------------------編輯--------- 拉多抽象類。

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

} 

阿里斯塔子

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

} 

然後,如果我返回List<Lado>如果y嘗試做getExtremo1()它doenst找到編譯符號(上拉多類沒有existant),試圖投輸出列表像List<Arista>但它沒有正常工作。

+3

的解決方法是將接口'Grafo'中的返回類型更改爲'List <?擴展Lado>'。但是,如果您不允許改變這一點,那麼您就被卡住了。 –

+0

問:你的哪些類實際*實現了* Grafo? – FoggyDay

+0

@FoggyDay該類實現在一個名爲GrafoDirigido的類中,另一個名爲Digrafo,這兩個工作在90%,我只需要使lados()函數正常工作。 pbabcdefp是的它的工作原理,不幸的是我不能改變給我的功能基地簽名。 謝謝。 – AlejandroDiaz

回答

0

試着改變你的界面:

公開名單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; 
} 

希望幫助!

+0

這裏只有第二個選項實際上可行。 –

+0

@LouisWasserman:我編輯並添加了另一個--OR--這將使他不需要泛型類型。 – anonymous

+0

新的第二選項也不起作用。 –

1

由於類ARTISTA也拉多類,你的初始化應該是

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

讓我知道它是否有幫助。 – MaxZoom

+0

它可以工作,但會產生其他問題,例如我在列表上迭代,然後編譯器會看到每個元素,因爲它是lado類的,如果我需要使用Arista類的某些方法,它會失敗。 謝謝你的時間。 – AlejandroDiaz

+0

迭代時,通過使用instanceOf運算符向對象詢問它是什麼類。 – MaxZoom

-1

因此,這些都是你的約束:

  • 你不能改變lados()方法返回類型(List<Lado>)。
  • 你想你的領域是的List<Arista>

1.複製陣列

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

2.結束語爲不可修改的列表*

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

3.類型擦除,不要這樣做,這是不安全

在返回之前擦除字段的泛型。不安全,因爲如果有人添加了一個對象Lado但它不是Arista到該列表中,您將有HeapPolution

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

這是一個可怕的想法,它會影響類型安全,並可能導致堆污染。 – Radiodef

+0

它編譯是不是問題。 'Foo類擴展Lado {}新的GraphoImpl()。lados()。add(new Foo());'它不**安全,** nobody **應該使用它。 – Radiodef

+0

好的,你擔心有人修改這個列表。點指出。我修改了答案以反映你的貢獻。 –

0

如果您不能更改方法返回類型或變量聲明,你可以返回一個副本:

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

或者你可以返回一個包裝:

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

unmodifiableList?我不這麼認爲。所有的好:) –

+0

複製工作,只需要檢查,當我收到回報,我可以看到檢查Arista類的屬性或功能。 謝謝你的時間。 – AlejandroDiaz