Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Collections: Pass collection of children as collection of parents

Say I have an interface and some classes:

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

Then I have a set of LocalizedButtons and when I call

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

I get that this method is not applicable for this arguments. If I try to overload this method as addComponents(Set<LocalizedButton> buttons) in LocalizedButtonsPanel, I get type erasure, of course.

May be some pattern is missed or the trick exists to deal with this architecture to implement correct adding the set of LocalizedButtons?


I've got the answer and I want to make my example more concrete - I have some validators in my implementation, so I need the collection type to be also stored as generic, that is simplified code I've got using the answer:

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

And in this case, it works

like image 755
shaman.sir Avatar asked Aug 03 '10 11:08

shaman.sir


1 Answers

Change the addComponents() signature to

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

so that the methods accepts sets of subclasses of Button. This way, you can pass a Set<LocalizedButton> as an argument, because LocalizedButton extends Button and therefore matches the parameter Type of Set<? extends Button>.

like image 174
f1sh Avatar answered Sep 23 '22 07:09

f1sh