Java集合:将子集合传递为父集合

发布于 2024-09-13 08:03:07 字数 2004 浏览 2 评论 0原文

假设我有一个接口和一些类:

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

,我发现此方法不适用于此参数。 如果我尝试在 LocalizedButtonsPanel 中将此方法重载为 addComponents(Setbuttons),当然,我会得到类型擦除。

可能会遗漏某些模式,或者存在处理此架构以实现正确添加 LocalizedButtons 集的技巧?


我已经得到了答案,我想让我的示例更加具体 - 我的实现中有一些验证器,所以我需要将集合类型也存储为通用类型,这是我使用答案得到的简化代码:

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

并且在这种情况下,它有效

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

动次打次papapa 2024-09-20 08:03:07

更改 addComponents() 签名,以便

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

该方法接受 Button 的子类集。
这样,您就可以将 Set 作为参数传递,因为 LocalizedButton 扩展了 Button,因此与 的参数 Type 匹配设置

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>.

分開簡單 2024-09-20 08:03:07

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

仅为按钮类型创建列表,而不为扩展该类型的对象创建列表。

You have

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

Should be

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

The list is created only for the type of button not for Object that extend that type.

愁杀 2024-09-20 08:03:07

Java 中参数化类型不是协变的。这很好,否则您将能够将 Dog 添加到列表中。已升级为 List。您可以在使用站点添加协方差,例如 List可以分配一个List并且你不能调用它的 add 方法。

Parameterised types are not covariant in Java. This is good, otherwise you would be able to add a Dog to a List<Cat> that had been upcast to List<Animal>. You can add covariance at the usage site, e.g., List<? extends Animal> can be assigned a List<Cat> and you can't call its add method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文