2013-02-23 67 views
6

我想實現並重寫不同返回類型的方法,而不必強制轉換返回類型。不用返回類型的java中的抽象方法沒有鑄造

public abstract class A { 
public abstract Object getValue(String content); 
} 

public class B extends A { 
public String getValue(String content) {...} 
} 

public class C extends A { 
public int getValue(String content) {...} 
} 


public class D extends A { 
public boolean getValue(String content) {...} 
} 

// Main loop: 
for (A a : allAs) 
{ 
// I want to use the method getValue() and corresponding to the type return a String, int or boolean without casting the return type 
} 

我的問題: 是否有可能無需被迫施放返回不同類型的? 抽象方法如何解決問題?

我認爲必須有一個解決方案,因爲編譯器應該知道的返回類型...

+0

您不能基於返回類型進行覆蓋。 – 2013-02-23 06:37:57

+0

而這個程序不會編譯 – 2013-02-23 06:38:23

回答

13

在你的例子中,類CD不會編譯。其中的重寫方法違反了Liskov substitution principle,也就是說,它們的返回類型與其父類不兼容。只要你願意放棄使用原語作爲你的返回類型,你所要做的就可以用泛型來完成。

abstract class A<T> { 
    public abstract T getValue(String content); 
} 

class B extends A<String> { 
    public String getValue(String content) { } 
} 

class C extends A<Integer> { 
    public Integer getValue(String content) { } 
} 

class D extends A<Boolean> { 
    public Boolean getValue(String content) { } 
} 
+0

謝謝。此代碼可以工作。然而,getValue()的返回類型是一個「Object」,所以我必須施放它。 – erwingun2010 2013-02-23 07:45:59

+0

@ erwingun2010如果你的方法有返回類型「Object」,你可能會實例化你的類錯誤。執行此操作:'A bInstance = new B();'如果不將類型添加到A聲明中,則抽象方法將返回'Object'。 – fiskeben 2014-04-03 06:56:15

3

你描述什麼是不可能的一般。但是,如果子類返回超類方法return的「窄」子類型,則稱其爲「協變返回類型」,並且自JDK 1.5以來,它在Java中被允許。然而,根據你的例子,我認爲協變回報並不是你想要的。

我假設你想要的是

for (A a : allAs) 
{ 
    String b = a.getValue(); 
    int c = a.getValue(); 
} 

這裏的問題,當然,編譯器無法知道在編譯時這兩個語句是正確的方式,而不能同時是正確的。

+0

這正是我想要的。我仍然不明白爲什麼編譯器無法在編譯時知道哪種返回類型是正確的。當我初始化allAs我使用=> allAs.add(new B()); allAs.add(new C()); – erwingun2010 2013-02-23 07:47:14

+0

在我展示的示例中,循環中的兩個語句都指的是'A'的_single_實例,它不能同時是'B'和'C'。編譯器應該如何知道它是什麼,直到運行時纔會發生? – 2013-02-23 17:56:52

0

在您的例子中,class B的定義是確定的,因爲StringObject子類。另外兩個不會編譯,因爲它們是原始類型。你可以用IntegerBoolean來替換它們來解決這個問題。

至於你的主循環,如果你正在遍歷它們作爲參考A,你將只能使用A的方法定義,該方法返回Object

2

您可以使用泛型。

public abstract class A<T> { 
    public abstract T getValue(String content); 
} 

public class B extends A<String> { 
    public String getValue(String content) {...} 
} 

etc ... int不作爲返回類型,但Integer會。

我不是在編譯器中鍵入因此可能會有錯別字......

正如吉姆和克里斯指出,如果要遍歷作爲,你只能得到「A」的結果,這是目的。

+0

謝謝。當然,我必須使用基元String,Boolean,Integer,... – erwingun2010 2013-02-23 07:50:08