将额外的代码插入Java for循环

时间:2014-02-15 02:04:32

标签: java for-loop foreach conditional-statements code-duplication

我有一批sprite(纹理OpenGL ES 2.0 Quads),我循环移动。这是我的代码的简化版本:

//'sprite' & other values have been are assumed to exist for the purpose of the question

public void moveQuadBatch(){

    //Loop for as many sprites as there are to draw
    for (loop = 0; loop < sprite.number; loop++){

        moveQuadNumber(loop); //this method will move the sprite that corresponds to the number loops so we can move through the entire batch and move each individual sprite


    }
}

现在,对于某些批次,有一个倒数计时器,或其他一些条件(并没有其他条件,如上所述)。因此,我为这些对象创建了一个类似的方法:

public void moveQuadBatchWithCheck(){

    //Loop for as many sprites as there are to draw
    for (loop = 0; loop < sprite.number; loop++){

        //Only do this if the particular sprite's countdown/delay counter has reached 0 (counting down from another method not seen here)
        if (sprite.delay[loop]<0){

            moveQuadNumber(loop); //this method will move the sprite that corresponds to the number loops so we can move through the entire batch and move each individual sprite

        }
    }
}

然而,由于存在大量代码重复,我对此并不完全满意。而不是有这两种方法是否有任何方法我可以使用第一个,并以某种方式“滑流”附加检查到for循环?或者以其他方式减少我在这里的重复?这是一个简单的例子,还有其他一些,目前我有多种方法都非常相似。

修改

如上所述,上述内容有所简化。我可以有一些for循环检查另一个值(例如延迟除外),有些可以检查2个条件。

4 个答案:

答案 0 :(得分:3)

public void moveQuadBatch(bool checkDelay) {
    for (loop = 0; loop < sprite.number; loop++){
        if (!checkDelay || sprite.delay[loop] < 0) {
             moveQuadNumber(loop);
        }
    }
}

现在moveQuadBatch(false)是您的第一个功能,moveQuadBatch(true)是您的第二个功能。


至于“插入额外的代码”,你基本上是在谈论功能。在Python中,一种优雅的方法是将函数传入和卸载所有逻辑到函数,例如:

    def moveQuadBatch(predicate=None):
        for loop, sprite in enumerate(self.sprites): 
            if not predicate or predicate(loop, sprite):
                self.moveQuadNumber(loop)

然后你会这样使用它:

inst.moveQuadBatch()  
inst.moveQuadBatch(lambda loop, sprite: sprite.delay[loop] < 0)
inst.moveQuadBatch(lambda loop, sprite: sprite.doesItBlend(loop))

你可以用Java做同样的事情,但不是很整齐:你必须定义一个谓词类及其实例。这就是B.J. Smegma所倡导的方法。

public interface QuadBatchPredicate {
    public boolean shouldMove(int loop, Sprite sprite);
}

你的功能如下:

public void moveQuadBatch(QuadBatchPredicate pred) {
    for (loop = 0; loop < sprite.number; loop++){
        if (pred == null || pred(loop, sprite)) {
             moveQuadNumber(loop);
        }
    }
}
public void moveQuadBatch() {
    moveQuadBatch(null);
}

然后您可以使用匿名类来定义谓词:

moveQuadBatch();
moveQuadBatch(new QuadBatchPredicate() {
    public boolean shouldMove(int loop, Sprite sprite) {
        return sprite.delay[loop] < 0;
    }
});
moveQuadBatch(new QuadBatchPredicate() {
    public boolean shouldMove(int loop, Sprite sprite) {
        return sprite.doesItBlend();
    }
});

比Python解决方案有点琐碎,但它得到了重点。现在,您可以通过在线定义谓词来“插入代码”,使其成为您想要的任何内容。另外,你可以保存经常使用的,所以你不要在整个地方重复它们:

QuadBatchPredicate checkBlends = new QuadBatchPredicate() {
    public boolean shouldMove(int loop, Sprite sprite) {
        return sprite.doesItBlend();
    }
};

答案 1 :(得分:2)

创建一个界面:

public interface MyInteface {
void do_something(int loop);
}

根据您的需要制作该界面的不同实现,例如

public class MyInterfaceImpl {
    public void do_something(int loop) {
         if (!checkDelay || sprite.delay[loop] < 0) {
              moveQuadNumber(loop);
         }
    }

然后你的方法看起来很简单:

public void moveQuadBatch(MyInterface interface) {
    for (int loop = 0; loop < sprite.number; loop++){
        interface.do_something(loop)
    }
}

答案 2 :(得分:1)

你可以为你的精灵添加“效果”。

public class Sprite {
    private boolean active = true;
    private ArrayList<Effect> effects = new ArrayList<>();

    public void update(int time) {
        for(Effect e: effects) {
            e.update(this, time);
        }
    }

    public void addEffect(Effect effect) {
        effects.add(effect);
    }

    public void setActive(boolean active) {
        this.active = active;
    }
}

public interface Effect {
    void update(Sprite sprite, int time);
}

public class Delay implements Effect {
    private int delay;

    public Delay(int delay) {
        this.delay = delay;
    }

    public void update(Sprite sprite, int time) {
        delay -= time;
        if(delay > 0) sprite.setActive(false);
        else sprite.setActive(true);
    }
}

答案 3 :(得分:0)

我会为延迟检查创建一个单独的方法,并改变你的方法,如下所示:

public void moveQuadBatchWithCheck(bool check){
    for (loop = 0; loop < sprite.number; loop++){
        if(check){
            if (sprite.delay[loop]<0){
                moveQuadNumber(loop); 
                }
       }
       else{
           moveQuadNumber(loop);
           }
    }

然后当你想用true检查调用方法时 在参数。

不确定这是否是您正在寻找的,但我希望它有所帮助。