【问题标题】:Problematic declaration using inheritance in generics在泛型中使用继承的有问题的声明
【发布时间】:2014-10-21 07:20:53
【问题描述】:

我有

LoginCommandExecutor implements CommandExecutor<LoginCommand>
LoginCommand implements Command

为什么这行会抛出编译错误:

CommandExecutor<Command> a = new LoginCommandExecutor(commander, null);

但它适用于以下两种情况:

CommandExecutor<? extends Command> a = new LoginCommandExecutor(commander, null);
CommandExecutor b = new LoginCommandExecutor(commander, null);

如果两者都工作,哪一个更可取?为什么?

因为我看到 a 和 b 在 IDE 中显示相同的方法

【问题讨论】:

    标签: java generics inheritance interface


    【解决方案1】:
    CommandExecutor b = new LoginCommandExecutor(commander, null);
    

    使用原始类型。绝对不应该使用它。

    CommandExecutor<? extends Command> a = new LoginCommandExecutor(commander, null);
    

    是正确的,但隐藏了您所拥有的实际上是CommandExecutor&lt;LoginCommand&gt; 的事实。您将无法向此执行器提交任何命令,因为执行器接受的命令类型未知。

    CommandExecutor<Command> a = new LoginCommandExecutor(commander, null);
    

    是错误的,因为 LoginCommandExecutor 只接受 LoginCommand,而 CommandExecutor&lt;Command&gt; 接受任何类型的命令。如果编译器接受了,你可以这样做

    CommandExecutor<Command> a = new LoginCommandExecutor(commander, null);
    a.submit(new WhateverCommand());
    

    【讨论】:

    • 谢谢。但这不是与 OOP 继承相反吗? CommandExecutor&lt;Command&gt; a 公开了 LoginCommand 无论如何实现的基类方法。不?反之亦然:这并不意味着LoginCommand 可以转换为任何继承基类的类(又名Command
    • LoginCommandExecutor 只能处理 LoginCommands。所以你真的不希望能够向它提交其他类型的命令。就像您不希望将整数存储到 List&lt;String&gt; 中一样。
    • 我只是不明白声明中的区别:CommandExecutor&lt;? extends Command&gt;CommandExecutor&lt;Command&gt;
    • CommandExecutor&lt;Command&gt; 表示“接受任何命令实例的命令执行器”。 CommandExecutor&lt;? extends Command&gt; 表示“接受未知命令子类实例的命令执行器”。由于您不知道实际的子类是什么,因此您无法向执行者提交任何内容。不过,您仍然可以从中获取命令,因为您知道它们都是 Command 子类的实例,因此也是 Command 的实例。谷歌“PECS”。
    • means "a command executor that accepts any instance of Command" 但这仍然可以。 LoginCommand implements Command。我希望所有这些都用许多命令填充地图
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多