A blog about software development and other software related matters

Blog Archive

Tuesday, December 16, 2008

Java statefull callbacks

Any programmer comes to know callbacks at some point or another, in Java it looks something like this:


public interface Callback {
void doCall();
}

public class CallbackCosumer {
public void execute(final Callback callback){
callback.doCall();
}
}

// usage
public class Main {
public static void main(String[] args) {
final CallbackConsumer consumer = new CallbackConsumer();
consumer.execute(new Callback() {
public void doCall() {
System.out.println("doing my callback thingy");
}
});
}
}

The biggest downside is that its hard to pass calling context state into the rigid callback interface, we could try something like:

public class CustomCallback <T> implements Callback {

private <T> state;

public void doCall() {
System.out.println(state);
}

public void setState(<T> state) {
this.state = state;
}
}

Note that this implementation is limiting, the doCall method has to work for any type T, custom behavior will require sub classing (not reasonable expectation from the callback provider).
A somewhat better (the most elegant that iv found to date) solution is to take advantage of another interface:

public interface StatefullCallback<T> extends Callback{
void addState(T state);
}

// Now we have a custom state object
public static class CustomState {
// fields ..
}

// And usage with a type matching logic
public static void main(String[] args) {
final CallbackConsumer consumer = new CallbackConsumer();
final StatefullCallback<CustomState> callback=new StatefullCallback<CustomState>() {
private CustomState state;

public void addState(final CustomState state) {
this.state = state;
}

public void doCall() {
// some custom logic that uses the custom state object
}
};
callback.addState(new CustomState());
consumer.execute(callback);
}

Its quite easy to see how its possible to pass multiple types of state objects into the callback execution context and do it with relative ease, closure-blessed languages require no such hacking.

No comments: