|
| ||||||||||||||
See also: class, registry, make, to_cxs
In normal programming, a class does not know what instances of it have been created. Applications which want to keep track of individual instances, for debugging, display or other purposes, need to explicitly store the object in a variable, field, or table.
Water's register method provides a versatile way for classes to automatically track their instances, allowing them to be distinguished and identified based on both program logic (when they were created) and business logic (their individual attributes). register is typically called at the end of the 'make' method for a class with an argument of the instance being created.
register provides two kinds of instance recording: serial_id registration and unique_id registration. serial_id registration assigns a unique serial number to each instance when it is created and allows the instances of a class to be easily retrieved by serial number. unique_id registration ensures that a particular combination of fields uniquely identify instances of a class and makes it possible to retrieve an instance based on a particular combination.
serial_id registration stores the serial number of
an instance in the '_serial_id' field of the instances and maintains a field
'_with_serial_id' on the class which is a vector of created instances. The
serial number can then be used to select the particular instance from
this vector. An instance of the 'boat' class with a serial number of
1138 can be referenced by the expression
boat._with_serial_id.1138.
uniquekey registration provides both a way to find instances based on a particular combination of fields and ensures that there is only one instance with each particular combination. This uniqueness can be very important to the business logic of an application as well as providing for potential performance improvements. On the business logic side, many applications create instances which correspond to single business objects (for instance, real world individuals (people, boats, cars, computers, etc) or virtual objects (bank accounts, access or distribution lists, inventories, etc). In nearly all of these cases, it is important that changes to representations of business objects be consistent: that changes to an account balance in one part of the program be immediately visible to other parts of the program. The easiest and safest way to do this is by having them be the same Water object, which is what register ensures.
On the performance side, it can be much faster to compare or lookup registered instances than to compare or lookup regular objects.
Both kinds of registration can be overriden by setting the '_dont_register' field on an instance.
register takes a two optional arguments: 'serial_id' and 'registry'.
The 'serial_id' argument is a boolean, defaulting to true, which
determines whether to do serial_id registration for the object. When
provided, 'registry' points to a registry object to be used for
uniquekey registration; when it isn't provided, register uses
(and creates if neccessary) a registry on the instance's parent. This
registry is created using two fields of the class being instantiated:
'_unique_key' specifies the key around which the registry is built and '_merge_method' (optional) specifies the method used to merge instances in the registry.
'_unique_key' is either a field name or a vector of field names. It indicates the field or combination of fields which uniquely identifies instances of the class. Whenever register is invoked and the _unique_key field is defined, register checks if there are any instances of the class that have the same unique id values as the instance being created. If no such instance exists, the instance being created is stored so that it can be found by future calls to register.
'_merge_method' controls what happens when an instance with the same
unique id does exist. It is a method called on the existing instance
and the new instance and returns a value which will both be stored
under the given unique id and returned by register. The merge method
is also called the first time an instance is registered, with a first
argument of false.
The default merge method, registry.merge_overlay, keeps the
older instance but overwrites any conflicting fields with values
from the new instance. Other merge methods are:
registry.merge_overwrite which uses the older instance but
makes its field values identical to the new instance, removing
fields if necessary;
registry.merge_replace which uses the
new instance and replaces the stored value (this may break business
logic identity);
registry.merge_ignore which simply returns the new instance,
but doesn't store it, setting the '_unregistered' field instead.
Here is an example of serial_id registration:
<class boat> <method make> .<register/> </method> </class> <set myboat=<boat/>/> <v myboat._serial_id boat._with_serial_id.0.<is myboat/>/>
![]() | <v 0 true/> |
Here is an example of unique_id registration, where the 'name' field provides the unique id:
<class boat name=req color='blue' _unique_key='name'> <method make> .<register/> </method> </class> <set myboat=<boat name="bluebelle" color='blue'/>/> <set stillmyboat=<boat name="bluebelle"/>/> stillmyboat.<set color='green'/> myboat.color
![]() | "green" |
Since myboat and stillmyboat are the same object, as guaranteed by register, changing the color of stillmyboat changes the color of myboat.
| Parameter key | Default value | Type |
| serial_id | false |
This determines whether all instances of the class are registered with a unique serial number (serial_id registration). Objects with serial numbers are not normally reclaimed by garbage collection as normal objects are. The serial_serial_id parameter may be set to false to avoid this problem or to simply save the space need to keep track of serial numbers.
Needs to be fixed
The formatting method to_cxs has special support for
serial_id instances. boat.<to_cxs only_print_instances=true/>
turns off the printing of the call to class and the printing of all
its attributes. It does however leave on the printing of the
of field and all the of fields of all the subclasses of
the class you are printing. Use only_print_instances=true when
you want to save the instances of a class in a file but not the
classes that they came from since you probably load them as part of
the loading of your application.
| Parameter key | Default value | Type |
| _unique_key | false |
When register is called, the value of this field (if not
false) determines the fields of an instance used to uniquely identify
it and guarantee the absolute identity of equivalent instances.
In practice, the fields specified in the key field should be read-only and not subject to change (since that would corrupt the registry), but registries do not currently check that this is so.
| Parameter key | Default value | Type |
| _merge_method | merge_overlay |
When register is called, the value of _merge_method is used
to merge distinct but logically equivalent instances of the class.
The default behaviour, implemented by registry.merge_overlay, simply
uses the existing object, overwriting any fields from the new instance
being registered. This method is also called when a new object is
registered for the first time, in which case the first argument is
simplfy false.
| Parameter key | Default value | Type |
| _dont_register | false |
When this field is set to true on an instance, register leaves
it alone, neither registering or merging it. This can be used to make
distinct instances which would otherwise be identical, e.g.
<class boat name=req color='blue' _unique_key='name' _other_keyed=opt> <method make> <register _subject/> </method> </class> <set myboat=<boat name="bluebelle" color='blue'/>/> <set notmyboat=<boat name="bluebelle" _dont_register=true/>/> notmyboat.<set color='green'/> myboat.color
![]() | "blue" |
| Parameter key | Default value | Type |
| _with_unique_key | false |
On classes with registered instances, this field contains a mapping from each instance's unique key to the corresponding instance.
<class boat name=req color='blue' _unique_key='name' _other_keyed=opt> <method make> <register _subject/> </method> </class> <set myboat=<boat name="bluebelle" color='blue'/>/> boat._with_unique_key."bluebelle".color
![]() | "blue" |
| Parameter key | Default value | Type |
| _with_serial_id | false |
On classes with serial_id registered instances, this field contains a mapping from each instance's serial_id to the corresponding instance.
© Copyright 2007 Clear Methods, Inc.