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> |
Free forum by Nabble | Edit this page |