在 Java for 循环中插入额外代码
Posted
技术标签:
【中文标题】在 Java for 循环中插入额外代码【英文标题】:Inserting extra code into Java for loops 【发布时间】:2014-03-14 14:08:32 【问题描述】:我有一批精灵(带纹理的 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 个条件。
【问题讨论】:
为方法添加一些参数。根据参数的值,您可以采取不同的操作。 您能举个例子解释一下@B.J.Smegma 吗?谢谢 查看 Claudiu 的回答。 【参考方案1】: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();
;
【讨论】:
感谢@Claudiu,减少 cmets?我总是读到那些不评论他们的代码的人的抱怨?关于“循环”变量,第一条评论解释说所有变量/对象都假定存在 - 这是为了避免不相关的代码。没关系,但是,如上所述,这仅适用于 2 种不同的可能性,在我的实际代码中,我还有很多其他的,有些对“延迟”等以外的东西进行了额外的检查......有什么方法可以使用main for 循环,但更改其中的代码以进行我需要检查的任何内容 - 谢谢! :-) @Zippy:你能举一些你做的检查的例子吗?这将有助于整理出一个答案。啊,谢谢我错过了第一条评论,我认为它不相关.. @Zippy:哦,关于更少的 cmets,我的意思是你不应该让 cmets 只说出代码的作用,例如int i; //i will be our loop iterator
、for (i=0; i < 100; i++) //loop i starting from 0 and ending at 99, incrementing by 1 each time
等。我知道sprite[delay] < 0
的意思是“只有在特定精灵的倒计时/延迟计数器达到 0 时才这样做”,不需要拼写出来 =)。实际上,如果您这样拼写,则更难阅读。
我明白,请随时编辑 cmets :-) 我总是喜欢尽可能多地发表评论,因为我觉得这会使问题更具可读性。
@Zippy:看看我的编辑是否更符合您的喜好。真的允许你使用任何你想要的谓词。函数式编程 FTW【参考方案2】:
我会为延迟检查创建一个单独的方法,并像这样更改您的方法:
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 在参数中。
虽然不确定这是否是您正在寻找的,但我希望它会有所帮助。
【讨论】:
同意,请参阅主要问题中的编辑。谢谢:-) 你说得对。我正在打电话,所以我花了一段时间来回答这个问题。现在我看到了你的回答,我觉得自己很愚蠢。【参考方案3】:制作这样的界面:
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)
【讨论】:
对@B.J.Smegma 非常感兴趣。所以基本上,我会在 MyInterfaceImpl 类中为我需要的每个可能的结果创建一个方法,然后把它放在我的循环中? 你将为你在 for 循环中所做的每一件不同的事情创建接口的实现。然后,您可以根据需要使用这些不同的实现来调用您的方法。 基本上是map
的精简实现,而我的是filter
的精简实现..我不喜欢Java
你是说我需要为每个可能的结果定义一个不同的接口/类吗?或者,例如在同一接口中有一个“doSomething(int loop)”,然后是一个 doSomethingElse(int loop)' 方法。如果是后者,我将如何调用所需的任何方法?我不能显式输入 interface.doSomethingElse(loop) ,因为这又意味着,有多个 moveQuadBatch() 方法会破坏目的。或者也许我不完全理解这一点?谢谢!【参考方案4】:
您可以为您的精灵添加“效果”。
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);
【讨论】:
以上是关于在 Java for 循环中插入额外代码的主要内容,如果未能解决你的问题,请参考以下文章