【问题标题】:Java: For each loop , Iteration over extended objectsJava:对于每个循环,迭代扩展对象
【发布时间】:2012-09-27 14:03:59
【问题描述】:

我的问题可能很简单,

我有一个类 Result 有一些内部字段、setter 和 getter。

此外,我还有 Special1Result 类,它扩展了 Result 并包含更多字段,Special2Result 包含更多数据。

在不同的班级Dispatcher,我写了以下方法:

processResults(List<? extends Result> results),只熟悉Result(我需要这个方法来查询扩展的Result对象中是否有特定的字段——我用的是注解)。

所以我决定使用扩展的 for-each 循环:for (Result res : results) {}

那么我的问题是什么?我试图在网上找到如何为扩展对象编写这个 for 循环,例如像这样for (? extends Results res: results){}

有可能吗?正确的写法是怎样的?

【问题讨论】:

    标签: java foreach polymorphism


    【解决方案1】:

    关于List<? extends Result>,您所知道的只是每个元素都是Result - 这就是您可以在增强的 for 循环语法中添加的所有内容。

    如果您需要未在Result 中声明的成员,则需要在循环内进行强制转换:

    for (Result result : results) {
        if (result instanceof CleverResult) {
            CleverResult clever = (CleverResult) result;
            // Use clever here
        }
    }
    

    想想如果你使用增强的 for 循环你会写什么 - 你仍然需要编写演员表,不是吗?

    当然,如果你知道列表应该真的只包含一种特定类型,你总是可以在循环中无条件地强制转换。

    【讨论】:

    • +1,谢谢,虽然我不能问什么是 instanceof ,因为我不知道调度程序类中不同类型的特殊结果
    • @Michael:那么你无论如何也不能明智地使用这种差异,所以没关系,对吧?为什么你想要有一个你无法预测的变量?
    • 当您与远程团队一起编程时经常使用它,负责框架并允许您扩展他们的对象,只要您使用预定义的格式,例如使用注释。我正在工作的产品实现了这种设计,我希望对其进行一些扩展。使用注释(@interface),您可以向超类的用户指示哪些字段很重要,哪些类型要检查等等......框架设计者仍然需要能够处理不同开发人员的扩展对象,而不知道有什么已实施。
    【解决方案2】:

    我正在尝试通过网络查找如何为扩展对象编写此 for 循环,例如像这样的

    for (? extends Results res: results){}
    

    不,这是不可能的:您不能静态键入在运行时动态提供的项目。

    正确的写法是怎样的?

    你已经在做:

    for (Results res: results) {
    }
    

    如果您想在该循环内测试Special2Result,您可以这样做,但通常它表明您的设计可以改进。更好的选择是使用双重分派机制,例如Visitor Pattern,来隐藏您的子类的特殊处理细节。

    【讨论】:

    • +1 谢谢,我会在这里检查如何使用访客模式。
    【解决方案3】:

    Java 有类型擦除——集合的具体类型参数在运行时不存在。

    因此,如果您有一个 List,java 编译器将确保没有代码会将任何不是 Result 子类的内容放入列表中。

    因此,在运行时,您的循环可以知道的所有内容都是 Result 的子类 - 因此循环它们的唯一方法是作为对 Result 的一组引用,以及作为结果存在的任何多态行为列表中的任何子类。

    【讨论】:

    • +1,谢谢,我虽然过去如果你将一个更大的扩展对象转换为一个更小的超类对象,你可能会失去类中的一些特性
    【解决方案4】:

    由于您的具体子类仅在字段性质上有所不同,因此我建议您从简单的多态性中受益。

    您最终会得到一个 Result 接口/抽象类,该类定义了一个 execute() 方法类,该方法类由您需要的任意数量的类或子类实现。

    因此,您的客户端代码只能使用:

    for (Result res : results){    //results being as a List<Result> type
      res.execute(); 
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-15
      • 1970-01-01
      • 1970-01-01
      • 2013-01-21
      • 2014-05-04
      • 2017-12-25
      • 1970-01-01
      • 2014-06-17
      • 2012-12-18
      相关资源
      最近更新 更多