revisiting the 'delegate' proposal

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

revisiting the 'delegate' proposal

Martin Lafaix

I would like to revisit the 'delegate' proposal I made last week.
Tying a delegate with an interface implemented by the class was
too restrictive, confusing and unnecessary.  (Shame on me :-)

So here is a reformulated proposal. (An html version of this
document is available on:

  http://www.mygale.org/~lafaix/netrexx/delegate.html

you may find it more readable.)

------------------------------------------------------------------
Introduction

The delegation pattern is of common use in the Object Oriented
Programming world.  While nothing in NetRexx prevents the use of
delegation, all work is left in the hand of the developer.

The design presented here for support of delegation tries to
removes as much unnecessary work as possible for the developer,
while preserving consistency and predictability.

Delegates

The properties instruction [NRL 105] is used to define the
attributes of following property variables.  The visibility of
properties may include a new alternative :  delegate.  Properties
with this form of visibility are known as delegates.  These are
properties of a known type that are private to the class, but
which are expected to provide some service.

The delegate attribute of a property is an alternative to the
public, private, indirect and inheritable attributes.  Like
private properties, delegates can only be accessed directly by
name from within the class in which they occur; other classes can
only access them using the service they provide (or other methods
that may use, or have a side-effect on, the properties).

Delegates may be transient or static. They may not be constant or volatile.

In detail, the rules used for generating automatic methods for a
property whose declared type is xxxx are as follows:

   1.A wrapper is generated for all public instance methods
     exposed by the xxxx class and its superclasses.  If the
     property is constant, these methods will be generated as
     static methods.
   2.If a class defines more than one delegate and if two of those
     delegates define an identical method, no wrapper is generated
     and an error is issued.  (To circumvent this, an
     implementation has to be provided for all ambiguous methods.)

A delegate may have a real type which is either a subtype of its
declared type or an implementation of it.  As stated above,
wrappers are only generated for methods defined in the declared
type.  For example, in

  properties indirect
  output = DataOutput RandomAccessFile("foo", "rw")

the generated methods are the ones defined by the DataOutput
interface.

Note that in all cases a method will only be generated if it would
not exactly match a method explicitly coded in the current class
or in one of its superclasses.

Examples

As a first example, lets take the case of a bean.  If we create a
bean with bound properties, the JavaBean design pattern requires
us to support PropertyChangeListeners and to fire
PropertyChangeEvents each time a bound property is modified.

This is a very repetitive task and, to prevent as much errors as
possible, the JavaBean library contains a PropertyChangeSupport
class which provides a default implementation to handle the
registration of PropertyChangeListeners and PropertyChangeEvents
dispatching.

A bean developer can either subclass the PropertyChangeSupport or
use an instance of this class to delegate the work to it.
Subclassing is not always possible, as Java and NetRexx have no
support for multiple inheritance (if the bean is, say, a Panel, it
can't be a PropertyChangeSupport at the same time).

So it usually implies the following piece of code to be added to
the bean:

  properties private
  pcs = PropertyChangeSupport(this)

  method addPropertyChangeListener(pcl = PropertyChangeListener) protect
    pcs.addPropertyChangeListener(pcl)  

  method removePropertyChangeListener(pcl = PropertyChangeListener) protect
    pcs.removePropertyChangeListener(pcl)

  method firePropertyChangeEvent(name = String, -
                                 oldValue = Object, -
                                 newValue = Object)
    pcs.firePropertyChangeEvent(name, oldValue, newValue)

This is quite long and repetitive, especially if many beans are to
be defined.  Worse, if a new method is added to the
PropertyChangeSupport class, the code of each bean has to be
updated.

Using this proposal would replace the above with the following two
lines:

  properties delegate
  pcs = PropertyChangeSupport(this)

If the definition of PropertyChangeSupport changes, a simple
recompilation will be sufficient in most cases.

As a second example, lets make a very simplistic instance counter.
To do that, we define an InstanceCounter class to handle the
counting:

  class InstanceCounter

    properties indirect constant
    instanceCount = 0

    method incInstanceCount protect
      instanceCount = instanceCount + 1

To add an instanceCounter to a class, we define a static delegate
in the class.  Then, each time a new instance is created, we call
the incInstanceCount (now) static method.  (In this example, the
count is very primitive, as it also includes subclasses instances.
It can easily be enhanced, but it's not the point we are trying to
make.)

  class ATest extends Component

    properties delegate static
    cpt = InstanceCounter()

    method ATest
      incInstanceCount

    ...

We can then at any time query the number of created instances:

  aTest1 = ATest()
  ...
  say ATest.getInstanceCount


Martin
--
[hidden email]
Team OS/2
http://www.mygale.org/~lafaix

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To unsubscribe from this mailing list ( ibm-netrexx ), please send a note to
[hidden email]
with the following message in the body of the note
unsubscribe ibm-netrexx <e-mail address>