2010-01-27 56 views
1

假設我有:泛型質疑

public interface Action<S extends Shape> { 
    public void start(S shape); 
} 

爲什麼我得到以下?

public <S extends Shape> void performAction(Action<S> action, Shape shape) { 
    action.start(shape); // error: cannot supply Shape 
} 

換句話說,在未來,可能我的Shape子類和Action s表示對它們進行操作,如:

Action<Rectangle> 
Action<Blob> 

我想有一個統一的接口,可以適用Action s到Shape的一堆不同的子類。

回答

5

我想你需要的東西是這樣的:

public <S extends Shape> void performAction(Action<S> action, S shape) { 
    action.start(shape); 
} 

然而,在這種情況下,它並不清楚什麼價值存在使用仿製藥,如果你感興趣的是Shape和它的子類。下面的代碼將完成同樣的事情。

public interface Action { 
    public void start(Shape someShape); 
} 

public void performAction(Action action, Shape someShape) { 
    action.start(someShape); 
} 

然而,如果Action類是完全通用的,可以用比Shape其它物體和它的子類來使用,那麼你可以做到以下幾點:

public interface Action<S> { 
    public void start(S target); 
} 

public <S> void performAction(Action<S> action, S target) { 
    action.start(target); 
} 
+0

+1。在原始代碼中,不能保證「形狀」是「行動」期望的任何類型。 – 2010-01-27 17:41:24

+0

在這種情況下,我認爲泛型只會讓事情複雜化。 – jjnguy 2010-01-27 17:46:00

+0

@jjnguy,在這種簡單的情況下,似乎沒有必要同意泛型。 – 2010-01-27 19:39:33

1

start簽名需要S,但你通過它Shape

1

因爲動作是爲了形狀的專業化,而不是任何形狀。

3

我不認爲你在這種情況下一定需要仿製藥。這裏是我會做什麼:

public interface Action { 
    public void start(Shape someShape); 
} 

public void performAction(Action action, Shape someShape) { 
    action.start(someShape); 
} 

然後你就可以通過擴展Shape到方法start()任何類型。

+0

但是假設Action需要在Shape的子類中使用某種方法,例如用於Rectangle的getWidth()方法。在這種情況下,爲Shape對象上的矩形運行一個Action需要投射,並且通常不再安全。該怎麼辦? – Jake 2010-01-27 19:40:04

+0

如果是這種情況,給Shape一個名爲'getWidth()'的方法,並在所有子類中正確覆蓋它。 – jjnguy 2010-01-27 19:54:28

+0

@Jake請參閱上面的評論。 – jjnguy 2010-01-27 19:55:12

1

對於基本需要,我建議:

public interface Action { 
    public void start(Shape shape); 
} 

或者,如果你需要輸入他們更強,你可以改變其他:

public <S extends Shape> void performAction(Action<S> action, S shape) { 
    action.start(shape); 
}