Java流控制问题

Java流控制问题,java,exception,iterator,control-flow,conceptual,Java,Exception,Iterator,Control Flow,Conceptual,我正在编写一个简单的2d游戏引擎。我已经决定了引擎的工作方式:它将由包含“事件”的对象组成,我的主游戏循环将在适当的时候触发这些事件 关于结构的更多信息: 每个GameObject都有一个updateEvent方法。 objectList是将接收更新事件的所有对象的列表。只有此列表中的对象才有游戏循环调用的updateEvent方法 我正试图在GameObject类中实现此方法(此规范是我希望该方法实现的): 因此,如果某个对象试图在更新事件中移除自身,则控制权应转移回游戏引擎: public

我正在编写一个简单的2d游戏引擎。我已经决定了引擎的工作方式:它将由包含“事件”的对象组成,我的主游戏循环将在适当的时候触发这些事件

关于结构的更多信息: 每个
GameObject
都有一个
updateEvent
方法。
objectList
是将接收更新事件的所有对象的列表。只有此列表中的对象才有游戏循环调用的updateEvent方法

我正试图在GameObject类中实现此方法(此规范是我希望该方法实现的):

因此,如果某个对象试图在更新事件中移除自身,则控制权应转移回游戏引擎:

public void updateEvent() {
    //object's update event
    remove(this);
    System.out.println("Should never reach here!");
}
这是我到目前为止所拥有的。它是有效的,但是我读到的关于使用异常进行流控制的文章越多,我就越不喜欢它,所以我想看看是否有其他选择

删除方法
public void移除(游戏对象go){
//添加到removedList
//已删除的标志
//如果从updateEvent内部删除self,则引发异常
}

游戏循环
for(游戏对象go:objectList){
试一试{
如果(!go.removed){
go.updateEvent();
}否则{
//对象已计划删除,不执行任何操作
}
}捕获(ObjectRemovedE异常){
//控制权已转移回游戏循环
//这里什么都不用做
}
}
//现在从objectList中删除removedList中的对象

2个问题:

  • 我假设实现上述移除方法的立即停止部分的唯一方法是抛出一个自定义异常并在游戏循环中捕获它,对吗?(我知道,使用异常进行流控制就像goto一样,这很糟糕。我只是想不出其他方法来做我想做的事情!)

  • 对于从列表中删除对象本身,一个对象可以删除列表中较低的对象。目前,我在执行任何代码之前检查一个删除的标志,并在每次传递结束时删除对象以避免并发修改。有没有更好的、最好是即时/非轮询的方法来实现这一点

  • [编辑]
    在阅读了你的答案后,我想我会改变方法规格。即时删除行为是我已经习惯于在不同的引擎中使用的,但是你是对的,它并不真正适合Java的工作方式。该走了,试着用一种稍微不同的思维方式来思考吧

    为什么不直接返回,即

    public void updateEvent() { 
        //object's update event 
        remove(this); 
        return;   
        //obviously unreachable 
        System.out.println("Should never reach here!");     }
    

    为什么不直接返回,即

    public void updateEvent() { 
        //object's update event 
        remove(this); 
        return;   
        //obviously unreachable 
        System.out.println("Should never reach here!");     }
    
    你为什么不:

    • 在运行循环的对象中维护objectList
    • 不要让游戏对象访问列表(为什么要访问?)
    • 让updateEvent函数返回一个布尔值。如果返回值为false,则父对象将从事件列表中删除该对象。return语句还用于终止事件函数的执行
      • 你为什么不:

        • 在运行循环的对象中维护objectList
        • 不要让游戏对象访问列表(为什么要访问?)
        • 让updateEvent函数返回一个布尔值。如果返回值为false,则父对象将从事件列表中删除该对象。return语句还用于终止事件函数的执行
          • @jball的答案很好--+1

            我使用过的另一种工作良好且可能稍微干净的方法是让updateEvent()方法返回布尔值。无论何时从updateEvent返回True,都会删除()对象

            这使事件循环能够更好地控制循环本身的执行方式,并消除类之间的一些不必要的绑定。

            @jball的答案很好--+1

            我使用过的另一种工作良好且可能稍微干净的方法是让updateEvent()方法返回布尔值。无论何时从updateEvent返回True,都会删除()对象


            这使您的事件循环能够更好地控制循环本身的执行方式,并删除类之间一些不必要的绑定。

            我同意,根据您的规范,异常方法是实现remove方法的最佳方法


            然而,也许你应该重新考虑一下规格。我将把updateEvent何时终止的决定权留给实现者。使用remove()调用终止是令人困惑的,并且需要对流控制使用异常。我认为调用remove()应该只改变船旗国。我认为在所有对象上循环,检查每个对象的removed标志没有真正的问题。

            我同意,根据您的规范,异常方法是实现remove方法的最佳方法


            然而,也许你应该重新考虑一下规格。我将把updateEvent何时终止的决定权留给实现者。使用remove()调用终止是令人困惑的,并且需要对流控制使用异常。我认为调用remove()应该只改变船旗国。在所有对象上循环,检查每个对象的删除标志,我看不出有什么真正的问题。

            我也这么想。要求立即停止执行,而不是使用异常来完成。除此之外,即使有例外,你仍然受客户的摆布。updateEvent实现可以很容易地捕获异常,而不是重新抛出异常,允许他们选择继续执行。要求立即停止执行,而不是使用异常来完成。除此之外,即使有例外,你仍然受客户的摆布。updateEvent实现可以很容易地捕获异常,而不会重新触发
            for(GameObject go : objectList) {
                try {
                    if (!go.removed) {
                        go.updateEvent();
                    } else {
                        //object is scheduled to be removed, do nothing
                    }
                } catch(ObjectRemovedException e) {
                    //control has been transferred back to the game loop
                    //no need to do anything here
                }
            }
            // now remove the objects that are in removedList from objectList
            
            public void updateEvent() { 
                //object's update event 
                remove(this); 
                return;   
                //obviously unreachable 
                System.out.println("Should never reach here!");     }