How can you BuildInterfaceImplementationPairs when the implementation will be different for each class that implements the interface?
You have defined an abstract component interface that allows components' services to be queried and connected to other components. The implementation of the component interface will be different for each concrete component type but you don't want component developers to be overly burdened by the component model; they should concentrate on implementing the functional aspects of their component rather than its "packaging".
This is especially useful in frameworks in which components are dynamically instantiated and plugged together, such as JavaBeans, PipesAndFilters or in my case, a Java framework for dynamically building transport protocols from lightweight components.
JavaBeans uses reflection to determine those properties of a bean that are not described by its associated info class.
The Regent transport framework [http://www-dse.doc.ic.ac.uk/~np2/regent] uses reflection to determine the services and control interfaces of protocol layers that have not overridden the default query methods.
JavaUnit (a unit testing framework) by ErichGamma and KentBeck uses it. The default implementation of a test case uses reflection to find all test methods in the test subclass.
http://www.javaworld.com/javaworld/javatips/jw-javatip57.html shows how to use coding conventions and reflection in a similar way to define and query applet parameters without having to write lots of boilerplate code for each new applet class. Source code is included.
JavaBeans components are classes that come with associated "packaging"; the packaging provides development tools with the information they need to support graphical composition of the beans. JavaBeans packaging is defined as a set of interfaces that expose the properties, events and methods of the bean. Implementing these interfaces by hand is a tedious task that involves writing boilerplate code many times, only changing a few names each time.
Therefore, rather than forcing programmers to implement the packaging interfaces themselves, the Bean implementors FallBackOnReflection: they provided an implementation of the packaging interfaces that uses reflection to determine the properties and events of a bean based on simple coding conventions. Thus programmers can concentrate on the functional aspects of their beans rather than wasting time writing the packaging.
One might ask, why not ditch the interfaces and rely only on reflection? In Java, invoking a method by reflection is about 100 times slower than using a polymorphic call, so you want to allow programmers to replace reflection if performance becomes a problem. Therefore you provide abstract interfaces that can be implemented by hand for speed and a default implementation that uses reflection.
There's another example in JavaUnit, where the test methods follow a certain naming convention which the core engine uses to discover and invoke them via reflection. Specifically, the code in TestSuite searches for method names beginning with "test". VectorTest? implements testCapacity(), testContains() and so forth, and TestSuite finds and calls them. Those methods are not part of some common interface.
Without reflection, we would either have to give the methods standard names like test1(), test2() etc, or else put each test into its own class with a single method called test().
Even better is if you can easily attach CustomMetaData to a method. So, instead of encoding semantic information into a method name you can explicitly mark methods as test methods. The ScarletLanguage uses this so you can simply write something like 'def test-contains() [test]'. C# also supports this sort of usage. -- JesseJones
Java 5 now supports annotations.
This page mirrored in JavaIdioms as of April 29, 2006