Handling instance arrays like single instances

In Java, I am looking for a generic template that means arrays of a given type (say Foo ) will allow the method call of the array instance. Behind the scenes, this will repeat all the Foo instances in the array and invoke the instance method for each of them.

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 you could create some kind of generic template for your custom types, which essentially did such things:

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

It is essentially syntactic sugar for:

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

My motivation is that someone can use varargs to:

 someHelper(fooInstance1,fooInstance2).Method1() 

Where someHelper() returns Foo[] .

If every call to Method1() returned a value, it would be even better if it were transferred to an array of return values ​​(where ReturnVals.size == Foos.size ).

In the worst case scenario, I would have to write a separate class to achieve this for each type for which I need this work, possibly using interfaces to describe the functionality applicable to individual instances and instance arrays.

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

Otherwise, if any languages ​​facilitate this inherently?

I appreciate that this will not work for all scenarios, but I believe it is at the discretion of the programmer.

Thank you very much

+4
source share
5 answers

You invoke the Composite Template . You can find the universal and reusable component implementation in the PerfectJPattern project to check the Composite documentation page and example , which matches the example in the GoF book.

A verbal copy of the corresponding part of the example, let's say you have an IGraphic interface and several implementations, for example. Rectangle and Line, 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(); 

Here's how it will 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 implementation contains the actual composite element, and does not implement / offer the Foo interface, you need to get it using the getComponent method. This is a little nuisance, and it is necessary because in Java there is no other way 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 adjusts the real composite component for you and returns the desired Foo interface type. This is implemented using dynamic proxies, but the implementation is type safe and fully component based, i.e. You do not need to create new Composite arrays that implement your interface.

+1
source

You can do it with reflection.

Create a universal class that, at runtime, scans all publicly available T methods and enters methods with the same signature and body that passes through all its objects and calls the same method on them.

The problem is how to call dynamically created methods. Since this is only possible through reflection, this means that any method call in your source code must be done through reflection.

+1
source

There are various ways to do this, most of them use wrapper objects, etc. .... However, if your desired type is an interface, you are in luck, it is really doable using dynamic proxies .

eg.

 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."); } } 

The obvious limitations are that A (that is, the type of object that you will use in calls to the multicast method, MUST BE AN INTERFACE.

Another obvious limitation is that a multicast entity can only return one return from all of these calls.

The code may look ugly when it's all in one place, but the createMulticastObject method is a method that you can use as a utility, and A and B already written. So dynamic proxies reduce regular wrappers, etc., so that:

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

+1
source

Look at the methods in apaches CollectionUtils . You will need to implement an interface for each method that you want to call in the list.

Example:

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

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

I do not know if there is a generic version.

Also try using a functional language (scala, haskell, ...). They make such things very easy.

0
source

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

Not really - not without a large number of templates, which means that less code is written by a damned loop.

Otherwise, if any languages ​​facilitate this inherently?

Most functional languages ​​support something like this. In Scala, you can do foos.foreach(_.Method1()) , where foreach is the method that calls the code block for all elements, and the underscore is an alias for the current element. Runnable code: http://ideone.com/QRtPlK

In Java 8, you can use collection thread representations along with method references to do something like this:

 foos.stream().forEach(Foo::method1); 
0
source

All Articles