Search |
||
Functional objects made easy with tigerPosted by alexwinston on January 19, 2005 at 6:49 AM PST
After reading CrazyBob's article about sudo closures in java some time ago I made The article was rather short but provided practical examples of how to use I felt that commons-collections abtraction of Predicates and Closures was a start Now I do not puport to be an english scholar by any means but when I began to To begin I created interfaces for Predicate(s) and Closure(s) as illustrated below.
public interface Predicate<T> {
public boolean evaluate(T t);
}
public interface Closure<T> {
public void execute(T t);
}
Unfortunately I needed to conceptualize Prepositions and Subjects as mentioned
public void testPreposition() {
Predicate<Student> isPassing = new Predicate<Student>() {
public boolean evaluate(Student s) {
return ((s.getGrade() == Grade.A || s.getGrade() == Grade.B));
}
};
Predicate<Student> isNotAbsent = new Predicate<Student>() {
public boolean evaluate(Student s) {
return s.getDaysAbsent() == 0;
}
};
final List<Student> honorRoll = new ArrayList<Student>();
Closure<Student> addToHonorRoll = new Closure<Student>() {
public void execute(Student student) {
honorRoll.add(student);
}
};
Student student = new Student(Grade.D, 0);
when(student, isNotAbsent, addToHonorRoll);
assertEquals(1, honorRoll.size());
assertEquals(0, honorRoll.get(0).getDaysAbsent());
honorRoll.clear();
List<Student> students = Arrays.asList(new Student[] {
new Student(Grade.A, 1), new Student(Grade.B, 0),
new Student(Grade.C, 0) });
foreach(students, isPassing, addToHonorRoll);
assertEquals(2, honorRoll.size());
assertEquals(Grade.A, honorRoll.get(0).getGrade());
assertEquals(Grade.B, honorRoll.get(1).getGrade());
honorRoll.clear();
}
I came to the conclusion that prepositions should be evaluated against subjects, when(student, isNotAbsent, addToHonorRoll); The preposition would evaluate the subject(student) against the predicate( The ability to evaluate Predicate(s) and Closure(s) against a Subject was at hand
public class Preposition {
public static void with(Object subject, Closure c) {
c.execute(subject);
}
public static void when(Object subject, Predicate p, Closure c) {
if (p.evaluate(subject))
Preposition.with(subject, c);
}
public static void foreach(Object[] subjects, Closure c) {
for (Object subject : subjects) {
Preposition.with(subject, c);
}
}
public static void foreach(Object[] subjects, Predicate p, Closure c) {
for (Object subject : subjects) {
Preposition.when(subject, p, c);
}
}
public static void foreach(Collection subjects, Closure c) {
for (Object subject : subjects) {
Preposition.with(subject, c);
}
}
public static void foreach(Collection subjects, Predicate p, Closure c) {
for (Object subject : subjects) {
Preposition.when(subject, p, c);
}
}
}
I could now use the following syntax to meet this requirement. foreach(subjects, isPassing, addToHonorRoll); This was a great start however as I began to port CrazyBob's example I found This refactoring evolved from the following test which is an attempt to get
public void testRecursivePreposition() {
final Predicate<Method> isPublic = new Predicate<Method>() {
public boolean evaluate(Method m) {
return Modifier.isPublic(m.getModifiers());
}
};
final Predicate<Method> isProtected = new Predicate<Method>() {
public boolean evaluate(Method m) {
return Modifier.isProtected(m.getModifiers());
}
};
final List<Method> methods = new ArrayList<Method>();
final Closure<Method> addMethod = new Closure<Method>() {
public void execute(Method m) {
methods.add(m);
}
};
Closure<Class> addMethods = new Closure<Class>() {
public void execute(Class c) {
foreach(c.getDeclaredMethods(), isPublic.or(isProtected), addMethod);
}
};
with(C.class, addMethods);
assertEquals(4, methods.size());
assertEquals("getA", methods.get(0).getName());
assertEquals("getAA", methods.get(1).getName());
assertEquals("getB", methods.get(2).getName());
assertEquals("getBB", methods.get(3).getName());
methods.clear();
foreach(C.class.getDeclaredMethods(), isProtected, addMethod);
assertEquals(2, methods.size());
assertEquals("getAA", methods.get(0).getName());
assertEquals("getBB", methods.get(1).getName());
methods.clear();
foreach(C.class.getInterfaces(), addMethods);
assertEquals(2, methods.size());
assertEquals("getA", methods.get(0).getName());
assertEquals("getB", methods.get(1).getName());
methods.clear();
}
interface A {
public void getA();
}
interface B {
public void getB();
}
class C implements A, B {
public void getA() { }
protected void getAA() { }
private void getAAA() { }
public void getB() { }
protected void getBB() { }
private void getBBB() { }
}
You will notice that a foreach is nested within the Closure addMethods which
public abstract class Predicate<T> {
public abstract boolean evaluate(T t);
public Predicate and(final Predicate p) {
return Conjunction.and(this, p);
}
public Predicate or(final Predicate p) {
return Conjunction.or(this, p);
}
}
public class Conjunction {
public static Predicate and(final Predicate p1, final Predicate p2) {
return new Predicate<Object>() {
public boolean evaluate(Object t) {
return p1.evaluate(t) && p2.evaluate(t);
}
};
}
public static Predicate or(final Predicate p1, final Predicate p2) {
return new Predicate<Object>() {
public boolean evaluate(Object t) {
return p1.evaluate(t) || p2.evaluate(t);
}
};
}
}
Obviously this is a rather simplistic example however it illustrates in my opinion very Unfortunately functional objects will never be fully realized until they On an unrelated note if someone knows why mozilla double spaces the code examples please post a comment. »
Related Topics >>
Patterns Comments
Comments are listed in date ascending order (oldest first)
|
||
|
|