Dynamic capabilities in Java
Overview
This is a discussion of adding dynamic capabilities to Java (specifically when
coming from Smalltalk)
The following is a reference to the main thread-point that this short paper is on:
Original Posting: Fourth normal form and normalization
gafni@vnet.ibm.com wrote:
> We have a prototype written in Smalltalk that heavily relies on using
> Smalltalk dynamic features such as:
> 1. Dynamically creating new classes
> 2. Dynamically adding instance variables to an existing class
> 3. Dynamically adding methods to an existing class
>
> We are considering writing the production solution in Java. Is it
> possible to implement workarounds so these features will work in Java?
> Any Ideas? How much work would it be?
It is certainly possible to make a Java program as dynamic as a
Smalltalk program, but you will need to do it through new instances of
existing (generalized) types as opposed to relying on the extensible
meta-class capabilities of Smalltalk.
For example, your items (2) and (3) are ways to maintain new kinds of
state and perform new kinds of behavior for existing objects. Both of
these can be done with encapsulated "Dictionaries of Objects", where the
objects are just state value holders for (2) and the objects are
Functors (blocks, closures, simple classes) for (3). This moves you a
step above core language capabilities, but the ultimate functionality is
the same:
anObject x.
becomes
(anObject getVariable: #x) value.
and
anObject perform: #foo.
becomes
(anObject getFunctor: #foo) execute.
The important aspect for migration to Java is that the interfaces for
the above are known at compile time. For the first we just need a
ValueHolder type interface:
interface ValueHolder {
Object getValue();
void setValue(Object newValue);
}
For the second we need a few variations of Functor types of interface:
interface Procedure0Arg extends Functor {
void run();
}
interface Function1Arg extends Functor {
Object getValueWith(Object arg);
}
etc.
And to pull it all together we would have something like:
interface DynamicObject {
ValueHolder getVariableNamed(String name);
Functor getFunctorNamed(String name);
//or return a type-specific Functor
Procedure0Arg getProcedure0ArgNamed(String name);
}
With this relatively limited set of interfaces, we can define all the
external behavior we require and then we just need suitably generic
implementations. We could also create somewhat optimized
implementations by generating new Classes that support the generic
protocol.
Although the above shows a very generalized approach, you should only
make the areas you require general (in the ways necessary at that
point). If all aspects of your whole program are very dynamic than it
would make more sense to keep with languages like Smalltalk, Python,
Lisp, etc. that inherently support those capabilities.
Do not consider Java's Reflection capabilities as worth anything in this
process except for (possibly) implementation prototyping support or
areas that have almost no performance restrictions.
Conversion process
Although it may be peculiar to do in Smalltalk, you could test out the
above capabilities with your existing Smalltalk prototype to get a feel
of the changes required. Make the rule simply: do not create new
classes or add methods/instance-variables to existing classes. Instead,
create new instances of these kinds of generalized classes
(ValueHolders, Functors, DynamicObjects). You will need more syntactic
glue but the functionality will be the same. After this conversion, the
movement to Java will be relatively painless.
--Mark
mark.fussell@chimu.com
|