2010-08-03 50 views
7

收集的通集說我有一個接口和一些類:Java集合:孩子的父母

public interface IPanel<ComponentType extends Component> { 
    public void addComponents(Set<ComponentType> components); 
    public ComponentType create(); 
} 

public class Button extends Component { } 

public class LocalizedButton extends Button { } 

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

public class LocalizedButtonsPanel extends ButtonsPanel { 
    public Button create() { return new LocalizedButton(); } 
} 

然後我有一組LocalizedButtons的,當我打電話

final LocalizedButtonsPanel localizedButtonsPanel = new LocalizedButtonsPanel(); 
final Set<LocalizedButton> localizedButtonsSet = new LinkedHashSet<LocalizedButton>(); 
localizedButtonsPanel.addComponents(localizedButtonsSet); 

我得到該方法不適用於這個參數。 如果我嘗試將addComponents(Set<LocalizedButton> buttons)中的方法重載爲LocalizedButtonsPanel,那麼當然我會進行類型擦除。

可能是某種模式被遺漏或存在處理這種架構的技巧來實現正確添加LocalizedButton集合嗎?


我已經得到了答案,我想我的例子更具體的 - 我有我的執行一些驗證,所以我需要集合類型來存儲爲通用的,即簡化代碼我使用應答已經得到了:

public interface IPanel<ComponentType extends Component, CollectionType extends Collection<? extends Component>> extends Validated<CollectionType> { 
    public void addComponents(CollectionType components); 
    public ComponentType create(); 
} 

public class Button extends Component { } 

public class LocalizedButton extends Button { } 

public class ButtonsPanel implements IPanel<Button, Set<? extends Button>> { 
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

public class LocalizedButtonsPanel extends ButtonsPanel { 
    public Button create() { return new LocalizedButton(); } 
} 

在這種情況下,它的工作原理

+0

有可能是(可能)類似的問題http://stackoverflow.com/questions/298305/,但那裏的答案打破了接口我有 – 2010-08-03 11:57:53

回答

6

更改addComponents()簽名

public void addComponents(Set<? extends Button> components) 

,這樣方法接受臺按鈕的子類。 這樣,您可以傳遞一個Set<LocalizedButton>作爲參數,因爲LocalizedButton延伸了Button,因此與參數類型Set<? extends Button>相匹配。

+0

哦,是的,謝謝。我的結構有點複雜(我將在問題中描述),但是我已經更正了我的泛型以適合您的建議,它確實適合:)。 – 2010-08-03 12:19:22

5

你有

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

public class ButtonsPanel implements IPanel<Button> { 
    public void addComponents(Set<? extends Button> components) { ... /* uses create() */ ; } 
    public Button create() { return new Button(); } 
} 

列表僅對按鈕的不是擴展該類型對象的類型即可。

+1

這個:'公共類ButtonsPanel實現IPanel <?擴展按鈕>' 將無法​​正常工作,因爲通配符不'implements'節的支持,如果我指定 這樣的:'公共類GenericButtonsPanel <按鈕類型擴展了Button>實現茁壯' 然後'LocalizedButtonsPanel延伸GenericButtonsPanel < LocalizedButton>'在這種情況下不會''ButtonsPanel'的孩子'擴展GenericButtonsPanel

+1

真的,我編輯了我的文章。 – 2010-08-03 12:28:48

0

參數化類型在Java中不是協變的。這是很好的,否則你將能夠添加一隻狗到列表<貓>已被upcast列表<動物>。您可以在使用地點添加協變量,例如列表<?擴展動物>可以分配一個列表<貓>,你不能調用它的add方法。