Java Tiger - Visitor return type

I've been playing with generics in the latest JDK (among other features) to see how many of the features are useful in my eternal JavaSauce project. Quite a few as it happens. Annotations, varargs, new for loop iteration, static imports. And generics. In particular generics for the Visitor Pattern. Here's what I had before Tiger (some class names changed to save typing):
public interface Visitable
{
    void accept(Visitor visitor);
}

public interface Visitor
{
    void visit(A visited);
    void visit(B visited);
    void visit(C visited);
}
These interfaces allow me to visit the A, B, and C classes which all live in the same package and particpate in a Composite relationship (as is often the case). Given the recursive whole-part relationships there's a strong temptation to make the return type boolean instead of void. However, some concrete Visitors don't need or use a return type so for these classes the void return type is preferable. There's a definite tension. Generics can help. Here's what I've now got:
public interface Visitable
{
    <R> R accept(Visitor<R> visitor);
}

public interface Visitor<R>
{
    R visit(A a);
    R visit(B b);
    R visit(C c);
}
One slight problem with this approach is that R can only be a reference type:
public final class SomeVisitor
    implements
        Visitor<boolean>  // compile time error
{    ...
}
A small Adapter can help to solve this:
public final class BooleanVisitorAdapter
    implements
        Visitor<Boolean>
{
    public BooleanVisitorAdapter(final BooleanVisitor adaptee)
    {
        this.adaptee = adaptee;
    }

    public Boolean visit(final A visited)
    {
        return Boolean.valueOf(adaptee.visit(visited));
    }

    public Boolean visit(final B visited)
    {
        return Boolean.valueOf(adaptee.visit(visited));
    }

    public Boolean visit(final C visited)
    {
        return Boolean.valueOf(adaptee.visit(visited));
    }

    private final BooleanVisitor adaptee;
}

public interface BooleanVisitor

{
    boolean visit(A visited);
    boolean visit(B visited);
    boolean visit(C visited);
}
Allowing:
someObject.accept(new BooleanVisitorAdapter(
    new BooleanVisitor()
    {
        public boolean visit(final A visited) { ... }
        public boolean visit(final B visited) { ... }
        public boolean visit(final C visited) { ... }
    }));
Note how the adapter creates a Boolean from a boolean. That could be handy; it could avoid the client writing
new Boolean(true)
which would cause needless pressure on the garbage collector (remember this is in a recursive context).

No comments:

Post a Comment