Question

In Java I'm looking for a generic template that means arrays of a given type (say Foo), will allow instance method calls upon the array. Behind-the-scenes this would translate to iterating over all Foo instances in the array, and calling the instance method upon each one.

Perhaps some code will demonstrate this point better:

public class Foo{

   public Foo(){}

   public void Method1(){}

}

So you have:

Foo foo = new Foo();
foo.Method1();

But could you make some generic template for your custom types that inherently made this kind of thing possible:

Foo[] foos = new Foo[]{new Foo(),new Foo(), new Foo()};
foos.Method1();

Which is essentially syntactic sugar for:

foreach(Foo f : foos){
  f.Method1();
}

My motivation is so that someone can use varargs such that:

someHelper(fooInstance1,fooInstance2).Method1()

Where someHelper() returns the Foo[].

If each Method1() invocation returned a value, it would be even better if this was wrapped in to an array of return values (where ReturnVals.size == Foos.size).

In the worst-case I'd have to write a separate class to achieve this for each type I need to have this work for, possibly using interfaces to describe functionality that applies to single instances and arrays of instances.

Is there any Java magic, Design Pattern or Generic jiggery-pokery that can elegantly achieve this?

Further, if not, do any languages facilitate this inherently?

I appreciate it wouldn't work for all scenarios, but that's at the discretion of the programmer I suppose.

Many thanks

Was it helpful?

Solution

You are calling for the Composite Pattern. You can find a componentized generic and reusable implementation in the project PerfectJPattern make sure to checkout the Composite documentation page and the example that matches the example in the GoF book.

Verbatim copy of the relevant part of the example, say you have IGraphic interface and a few implementations, e.g. Rectangle and Line, then you can do:

// build the composite
IComposite<IGraphic> myComposite = new Composite<IGraphic>(IGraphic.class);
myComposite.add(new Rectangle());                
myComposite.add(new Line());
myComposite.add(new Line());

// use the composite, invokes the IGraphic#draw() in the 
// underlying Rectangle and two Line instances
myComposite.getComponent().draw();

This is how it would work for your specific case:

Foo fooInstance1 = new Foo();
Foo fooInstance2 = new Foo();
IComposite<Foo> myComposite = new Composite<Foo>(Foo.class);
myComposite.add(fooInstance1);    
myComposite.add(fooInstance2);    
// invokes Method1 on instance1 and instance2 transparently
myComposite.getComponent().Method1();

// alternatively do
Foo myCompositeFoo = myComposite.getComponent();
// pass this myCompositeFoo around and do
myCompositeFoo.Method1();

Note that the IComposite reusable implementation holds the actual composite and it does not implement/offer the Foo interface, you rather have to get hold of it via the getComponent method. This is a small nuisance and it is needed because there is no other way in Java to create an instance of something (in this case Composite) that implements any arbitrary and statically unknown interface. The best I can do is give you a Composite that underneath builds a true composite component for you and returns your desired interface type Foo. This is implemented using Dynamic proxies, but the implementation is type-safe and fully componentized i.e. you dont have to create any new Composite arrays that implement your interface.

OTHER TIPS

You could do this with reflection.

Create a generic class which at runtime looks at all the public methods of T and injects into itself methods with the same signature and a body which loops through all its objects and calls the same method on them.

The problem with this is how to call dynamically created methods. Since this would only be possible through reflection it means that any method calls in your original code would have to be done via reflection.

There are various ways for doing this, most use wrapper objects etc... However if your desired type is an interface, you're in luck, this is actually doable using dynamic proxies.

E.g.

public static void main(String[] args) throws IOException {
    B[] objs = {new B(), new B(), new B()};
    A oneForAll = createMulticastObject(objs, A.class);
    oneForAll.print();
}

@SuppressWarnings("unchecked")
public static <T, U extends T> T createMulticastObject(final U[] targets, Class<T> interfaceClass) {
    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] {interfaceClass}, new InvocationHandler() {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object ret = null;
            for (U target : targets) {
                ret = method.invoke(target, args);
            }
            return ret;
        }
    });
}


interface A {
    void print();
}

static class B implements A {
    @Override
    public void print() {
        System.out.println("Invoked.");
    }
}

Obvious limitations are that A (that is the type of object you'll be using in multicasting method calls MUST BE AN INTERFACE.

Another obvious limitation is that the multicasting object can only return a single return from all those invocations.

Code may look ugly when it's all in one place, but createMulticastObject method is a method you can use as an utility method and A and B are already written anyway. So dynamic proxies reduce the usual wrappers etc to:

A oneForAll = createMulticastObject(objs, A.class);

Look at the methods in apaches's CollectionUtils. You'll have to implement an interface for each method you want to call on a list.

Example:

CollectionUtils.collect(foos, new Transformer() {
    public Object transform(Object foo) {
        return ((Foo) foo).method();
    }
});

Here I used an anymous class, but you can also implement Transformer in a separate class and reuse it.

I don't know if a version with generics exists.

Also try a functionnal language (scala, haskell, …). They make this kind of things very easy to do.

Is there any Java magic, Design Pattern or Generic jiggery-pokery that can elegantly achieve this?

Not really - not without a lot of boilerplate, meaning it's less code writing the damned loop yourself.

Further, if not, do any languages facilitate this inherently?

Most functional-ish languages support something like it. In Scala, you could do foos.foreach(_.Method1()), where foreach is a method that invokes a code block on all elements, and the underscore is an alias for the current element. Runnable code: http://ideone.com/QRtPlK

In Java 8, you'll be able to use stream views of collection along with method references to do something like this:

foos.stream().forEach(Foo::method1);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top