2012-06-19 34 views
3

我有一個方法foo如何從一個不可知的函數調用多態函數?

void foo (String x) { ... } 
void foo (Integer x) { ... } 

,我想從不關心參數的方法調用它:

void bar (Iterable i) { 
    ... 
    for (Object x : i) foo(x); // this is the only time i is used 
    ... 
} 

上面的代碼中抱怨說foo(Object)沒有定義,並且當我想補充

void foo (Object x) { throw new Exception; } 

然後bar(Iterable<String>)調用,而不是foo(String)和救援人員到場這是個例外。

如何避免使bar(Iterable<String>)bar(Iterable<Integer>)有兩個文本相同的定義?

我想我應該能逃脫類似

<T> void bar (Iterable<T> i) { 
    ... 
    for (T x : i) foo(x); // this is the only time i is used 
    ... 
} 

但後來我得到cannot find foo(T)錯誤。

+0

HTTP的可能重複:// stackoverflow.com/questions/4086523/patterns-to-compensate-for-lack-of-runtime-method-lookup-based-on-polymorphic-ar – Alex

回答

1

想一想:如果xObject,應該調用foo的哪個版本?

這就是JVM所面臨的問題。

如果你想要一個真正的多態方法,那麼你需要明確地寫一個。然後這種方法可以通過內省檢查Object,看看它的實際類型是什麼,然後調用適當的方法。

,你可以仔細看看foo做什麼。它只是調用Object定義的方法嗎?如果是這樣,只需創建一個void foo(Object x)方法來完成必要的操作。

2

您面臨的問題是重載的方法在編譯時綁定。在你的例子中,編譯器試圖找出調用哪個方法。然而,在你的例子中最強的靜態類型x是Object,並且沒有方法foo(Object),所以編譯器說它不能調用適當的方法。

如果您添加foo(Object)方法,無論x的實際運行時類型是什麼,您都將始終調用foo(Object)方法。

此問題擴展到使用泛型。由於T可以是任何類型,所以您必須具有通用方法foo(T),否則您的代碼將無法編譯。但是,如果添加該方法,則會失去使這些方法在不同參數類型之間辨別的能力,因爲只會調用foo(T)

解決此問題的唯一方法是通過逐個案例檢查並進行類似其他提議的答案。除非參數類型是您定義的類,並且它們都可以實現通用接口。然後,你可以這樣做:

interface ArgumentType { 
    void callback(FooClass c); 
} 

class YourClassA implements ArgumentType { 
    void callback(FooClass c) { 
     c.foo(this); 
    } 
} 

FooClass仍然要對每一個實現類的ArgumentType一個foo()方法,但這種方式,您可以通過類型不可知的選擇。

+0

你能解釋一下「最強靜態類型」是什麼意思嗎?謝謝! – Miquel

+1

「最強靜態類型」我的意思是編譯器可以爲變量x推斷的最具體的類型。例如,原則上如果你有這樣的代碼:Object x; x = new Integer(); FOO(X);一個聰明的編譯器可以發現在呼叫站點x的類型是Integer,並且可以調用適當的方法。在你的例子中,這是不可能的,因爲沒有什麼暗示你的代碼中的類型。因此,編譯器知道的「最強」類型是Object。 – Jochen

+0

感謝您的解釋! – Miquel

1

麻煩的是你正在試圖找到foo(Object x)而雖然字符串和整數都是對象,並非所有的對象都是字符串或整數,並且java不縮小到正確的類。

我或許會建議創建一個方法,如:

void foo(Object o){ 
    if (o instanceof String){ 
     String s = (String) o; 
     //Deal with s 
    } else if (o instanceof Integer){ 
     Integer i = (Integer) o; 
     //Deal with i 
    } 
} 

此外,如果使用的是仿製藥,無論如何,你不應該將原料迭代器,酒吧

相關問題