Closures MultiClosures - UnquietCode/Closures-for-Java GitHub Wiki
MultiClosures are a sort of "Closure collection". A MultiClosure supports 7 run operations, being 0-6 and varargs. Not all of the methods have to be implemented, and one can check for implemented methods by using isImplemented
. MultiClosures also have their own views.
Another interesting feature is that a MultiClosure can spawn views for each of its closure types. Further, implementing a vararg method ensures that all run operations will be implicity implemented. See the examples below for more information.
public void multiclosureBasics() {
// Multiclosures are like an abstract collection of other closures. They can support 0-6 arguments
// and vararg. Any method not implemented by you will throw an exception.
// The vararg method functions as a fallback for any unimplemented versions, if it is itself defined.
// They support views just like the other classes, and can even offer individual views for each
// of the closure types 0-6 and the unified ClosureView.
// Note that here the Overrides are optional, as the class does not require explicitly
// implementing the methods. It's pick and choose.
MultiClosure<String> helloMaker = new AbstractMultiClosure() {
String greeting = "Hello";
public Object run(Object p1) {
return greeting + " " + p1;
}
public @Override Object run(Object p1, Object p2) {
return greeting + " " + p1 + " and " + p2;
}
public @Override Object run(Object...args) {
StringBuilder sb = new StringBuilder();
sb.append(greeting).append(" to");
int lcv = 0;
for (Object o : args) {
String s = (String) o;
sb.append(" ").append(s);
if (lcv == args.length-2)
sb.append(", and");
else if (lcv < args.length-1)
sb.append(",");
++lcv;
}
return sb.toString();
}
};
out(helloMaker.run("Bob"));
out(helloMaker.run("Allan", "Susan"));
out(helloMaker.run("Jennifer", "Alexander", "Ryan", "Chris"));
out();
// We can try to get a more constrained versions of our helloMaker
Closure1View<String, String> singles = helloMaker.toClosure1();
out(singles.run("Steven"));
// Of course, you don't have to type them if you don't want to.
Closure2View doubles = helloMaker.toClosure2();
out(doubles.run("Tabitha", "Aragorn"));
// We didn't define a 3 argument version, but we did define a vararg, so it will work.
Closure3View<String, String, String, String> fallback = helloMaker.toClosure3();
out(fallback.run("Arnold", "Julie", "Marissa"));
// However, if we did not define a vararg version, we would have gotten an exception at runtime!
// We can curry the MultiClosure too.
out();
helloMaker.curry(1, "Goodbye");
out(helloMaker.run("Bob", "Allan", "Susan", "Jennifer", "Alexander", "Ryan", "Chris"));
// Remember though that the views are affected.
out();
ClosureView closure = helloMaker.toClosure();
helloMaker.curry(1, "Welcome back");
out(closure.run("Bob", "Allan", "Susan", "Jennifer", "Alexander", "Ryan", "Chris"));
}
public void mcTest() {
// MultiClosures will let you know which of their methods have been implemented.
// They must be implemented using Object types in the parameters.
// Use @Override annotations if that helps.
MultiClosure<String> helloMaker = new AbstractMultiClosure<String>() {
public @Override String run(Object p1) {
return "hello " + p1;
}
public @Override String run(Object p1, Object p2) {
return "hello " + p1 + " and " + p2;
}
public String run(String p1) { // This does NOT override any base methods!
return "d'oh " + p1;
}
};
// We can figure out what's implemented.
for (int i = -1; i < 8; ++i) {
out(i + " : " + helloMaker.isImplemented(i));
}
out();
out(helloMaker.run(1)); // ok
out(helloMaker.run(1,2)); // fine
//out(helloMaker.run(1,2,3)); // This will throw an exception (NotImplementedException).
}