Heya /prog/. I'm programming in java and there's something that really bothers me about my code. I'll write pseudocode so it's easier to see what I mean so don't get picky on syntax.
void onUpdate() {
switch(action) {
case IDLE: idle(); break;
case JUMPING: jump(); break;
case MOVINGRIGHT: moveRight(); break;
...
}
}
}
Now this really bothers me because you have this pile of ifs depending on status. It would, in my opinion, look much better if action was a pointer to a function.
But apparently java doesn't have this functionality. Or does it?
What do you think? Have any solutions to this?
Name:
Anonymous2012-08-09 9:36
It's possible, but you're going to have to do a lot of exception handling (or rethrow them packed in RuntimeException) and if you refactor your methods, then the refactoring tool won't pick up this stuff without some additional work. Take a look at java.lang.reflection.
I don't know the parameter list by heart, but something similar should do:
class Entity{
Method reflectiveMethod;
static {
m = Entity.class.getMethod("idle");
}
void setAction(String mName) {
m = getClass().getMethod(mName);
}
void onUpdate() {
m.invoke(this);
}
}
Generally, java.lang.reflection can do anything that a more dynamic language could do, but it can be quite a hassle to handle it. Also, in this particular case, you're probably better off just using an internal state instance and dynamic binding or (since your code looks like it is going to be used for a game) do it the way you do, because it's pretty fast and does not waste memory or CPU time on state change.
Also, I don't know how far the code you posted here strays from the actual code for sake of simplicity, but it seems like you could entirely avoid the problem by not using a software design that totally sucks.
public void onUpdate() {
currentAction.execute();
}
}
Name:
Anonymous2012-08-09 11:13
I don't know Java well, but can't you do something like the following (in CLOS)? (defclass action () ())
(defclass idle (action) ())
(defclass move-right (action) ())
(defclass jump (action) ())
Before some LISPPER gets offended, I want to write: of course, it would look cleaner with eql specialisers or functions, but I assume Java doesn't have that.
>>8
Wow, we wrote basically the same thing when neither of us had seen the other yet.
>>13
It would work without but only because of lisp being lisp. If there was static typing it would be necessary to provide a root class that all actions inherit from so that you would have a name for their collective type.
Java bytecode has a direct indexed jump instruction which is what a switch would compile to.
The JIT should be able to compile that to an indirect jump, so your initial solution would be the most efficient.
>>6
This is the verbose (and "OOP") way to do it, taking advantage of the fact that you can have variables of class type and storing different objects with methods in them, but I recommend against that unless those actions have their own independent state.
But if you really want to use function pointers, switch to a language that has them!
yeah, the entity can be passed as a parameter instead. This allows for the action to be stateless and statically initialized and shared. So changing an objects action is just reassigning a reference rather than creating a new object.
class Main {
public static void main(String[] args) {
Dog xe = new Dog(ActionIdle.instance, "xe", .6f);
int moments = 10;
for(int moment = 0; moment < moments; moment++) {
xe.onUpdate();
}
}
}