tags:

views:

89

answers:

3

I'm writing a simple Java 2D game, displaying a grid. The grid is (for the moment) a simple 2 dimensional array of specific game cells:

int height = 10;
int width = 10;
MyObject[][] table = new MyObject[height][width];

Often, I have to perform a specific method of my object over the full table:

for(int y = 0; y < height; y++) {
    for(int x = 0; x < width; x++) {
        table[y][x].MyMethod();
    }
}

I have dozens of methods for my cells (computing game rules, etc.), and it gets very tiresome to have to write always the same block of code with just the name of the method (occasionnaly, with a parameter) changing.
Is there some shortcut, or some trick, in Java, to allow an easier and more readable approach:

table.MyMethod();

SomeFactory(table, MyMethod);

I'm willing to change the design of my table, say, to turn it into a class, if possible using generics so as to allow reusability. I'm quite aware such things exist for values (fill method of Arrays), but is there a way to let methods be a dynamic parameter?

Thanks for your help.

+2  A: 

You'd need to have an interface, e.g.

public interface Action<T> {
    void apply(T item)
}

Then implement Action<MyObject> and turn your loop into:

public void applyToAll(Action<MyObject> action) {
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++) {
            action(table[y][x]);
        }
    }
}

Unfortunately this isn't as neat in Java as it would be in C# with delegates, but until we get closures in Java it's about the closest you'll get.

You can always implement the interface like this:

private static void MY_METHOD_ACTION = new Action<MyObject>() {
    @Override public void apply(MyObject item) {
        myMethod(item);
    }
};

That's not as neat when myMethod is an instance method of course... you'd need a new instance of Action<MyObject> for each instance of the class containing myMethod but it's useful for static methods.

Of course, if you're happy to implement Action<MyObject> directly, this isn't an issue.

Jon Skeet
A: 

This works, but you have to implement a lot of code, since you need multiple lines for each method.

I found a better solution, using reflection :
1) Create a generic function passing the name and the parameters of the method, as a vararg :

public void actionCall(String methodName, Object... parameters) {

2) For each parameter find its class (watch out for primitives types)
3) Find method using either :

yourClass.class.getMethod(name, parameterClasses)
yourObject.getClass().getMethod(name, parameterClasses)

4) Parse table and for each cell use :

method.invoke(myTable[y][x], params)

Then you just have to call the function like this, for each method, no additional code needed :

actionAll("methodName", paramValue);

It works the same for constructors (getConstructor).
It gets complicated when you have to get returned values, if someone had an idea ?

SXL
A: 

The most pragmatic solution would be to define a template in your IDE or editor so that the repetitive code can be inserted with a single key combo. Due to Java's lack of closures or delegates and the more verbose syntax for anonymous classes, the resulting code might even be shorter than the "generic" solution.

Additionally, (and unless your method call needs the indexes as parameter) you can use the "enhanced for loop" for a cleaner syntax:

for(MyObject[] row: table) {
    for(MyObject cell : row) {
        cell.MyMethod();
    }
}
Michael Borgwardt