Reusability is the facility to use existing objects and code to create new applications.
For object reusability, use Copy / Paste properties; property classes; object groups; subclassing and copying for certain objects, property classes, object Groups, and object libraries across form modules; and template forms as a base for new forms.
For code reusability, use copying of triggers and program units across modules, and create form libraries or reference triggers across form modules. Also, the triggers attached to property classes, triggers and program units (from Forms 5.x onwards) in object groups, triggers and program units in object libraries, and the code reused from template forms contribute to code reusability.
Subclassing is the act of making an object inherit the properties of a base object, including code. You achieve it in five ways:
- Applying a property class to an object
- Dragging and dropping objects across form modules
- Dragging and dropping an object group across form modules
- Dragging and dropping an object from an object library
- Attaching a smart class to an object
In Figure 6.2, you noticed a red arrow on the left side of each button item. This is because, when a property class is applied to an object, it (the object) is subclassed.
Subclassing has the following characteristics:
- Subclassing can create new instances of the source object, such as when dragging from an object library into a form module.
- Subclassing allows you to redefine most of the inherited property values, including totally recoding subclassed triggers.
- Child objects of a source object, when subclassed from another object, reflect the new properties in the children of the parent subclassed object.
- When an object is subclassed from a property class, the properties in the property class are blindly inherited by the object. The point to be noted here is that Forms should be intelligent enough to ignore the inherited property and not mark it as inherited if it has the same value as the default value of that property in the subclassed object.
- Subclassing cannot add new properties to objects but can assign new properties to them. For example, a subclassed property class can be populated with an extra set of properties and their values, but it is not possible to extend the pool by adding altogether new properties.
- Do not work on the source form with a target subclassed form open .
- Subclassed objects can be specialized by modifying the inherited properties. Even subclassed trigger code can be changed. Referencing does not allow this kind of specialization.
Subclassing and Copying
You can copy or subclass across modules stored in a database or file system. When you subclass objects, the properties of the subclassed objects can be modified in the target module. This is an enhanced feature over referencing (available in Forms 4.5), in which only certain properties of the referenced objects can be modified in the target module ”for example,
- For blocks, only the block name and comment can be changed.
- For items, the canvas view, comment, item name, and X,Y position can be changed.
- For triggers, only the comment can be changed.
- These changes are not reflected in the source form.
- When you copy a referenced object, the resulting object is also a referenced object.
Object groups enable you to reuse sets of functionally related objects by subclassing or copying the set as a whole. Again, consider the standard toolbar application. To construct such a toolbar, the following Forms objects can be used:
- A block named TOOLBAR with individual button items
- A canvas named CANVAS_TOOLBAR
- A property class named PC_ICONICBUTTON
These three Forms objects can be grouped together to form an object group, as shown in Figure 6.3.
Figure 6.3. An example of an object group.
This object group can in turn be subclassed or copied across multiple forms where such a toolbar is required.
Here are some things to keep in mind:
- Base-level objects owned by blocks cannot be placed in an object group: Only items, item-level triggers, block-level triggers, relations, and so on, can be. Individual property classes, visual attributes, canvases, windows , alerts, record groups, LOVS, and so on, can be the children of an object group.
- Object groups can contain program units from Forms 5.x on.
- An object group cannot contain another object group.
- Deleting an object group does not delete the objects it contains.
- When an object is deleted, it is deleted from its object group automatically.
- Object groups store only pointers to objects, not copies of objects. Therefore, creating an object group does not increase module size significantly.
Object Libraries and Subclassing by Means of Smart Classes
In the section under subclassing, I discuss five ways of subclassing. Of these, the most intelligent way is smart-classing. Smart classes are part of object libraries.
An object library is similar to a Forms library in that it is sharable across forms. The only thing extra here is, an object library can contain both Forms objects and code. Creating an object library involves the following steps:
- Create a module of type Object Library by double-clicking the Object Libraries node in the Object Navigator.
- Add objects to it by dragging them from the Object Navigator and dropping them into the object library.
- Mark them as smart classes. This is done by selecting the Object option in the menu and clicking on the Smart Classes suboption under it. The resulting smart class can be reused by a different object of the same type, in the same form or a different form. To do this, select the target object, right-click on it, and choose the corresponding smart class object under the Smart Classes node under it.
The object group OBJECT_TOOLBAR created in the preceding section can be added to an object library and marked as a smart class. Figure 6.4 shows how this is done.
Figure 6.4. An example of an object library and smart classing objects in it.
Marking individual objects in an object library as smart classes is not mandatory, but doing so creates a higher level of subclassing.
There is some difference between subclassing by means of a smart class and the other subclassing methods . The primary difference is that the first is the most intelligent way. The following tips suggest why smart classes are smart, and explain other related points:
- An object's smart classes pertain to only those classes that make sense for the object. In other words, a block smart class doesn't appear in the list of smart classes for a trigger object. The same holds true when a smart class is dragged from the object library and dropped in the Object Navigator.
- When a smart class is chosen for an object by clicking the right mouse button, the object under consideration will inherit the properties from the smart class object. The name of the target object will remain the same.
- Only those properties that make sense for the object are inherited.
- Smart-classed child objects cannot be deleted exclusively.
- Only those smart classes corresponding to the given object type are displayed in the Smart Classes list, when applying a smart class to an existing object. For example, when applying a smart class for a block object, a Property Class Smart Class is not shown in the list even though applying a property class to a block makes sense. This is an appreciable amount of smartness.
- Nested inheritance is supported. If a block is based on a block smart class that is based on a property class, the properties in the property class are inherited by the target block. This is true when you apply the smart class to the target block by choosing from the smart class list or by dragging and dropping a smart class from the object library.
- Smart class triggers enable the inheritance of their trigger text by a trigger, which doesn't make sense for the corresponding object, nor are the two triggers compatible. Consider a POST-QUERY trigger that exists as a smart class in an object library. Choosing it from the list of smart classes for an item that already has a WHEN-NEW-ITEM-INSTANCE trigger defined (by right-clicking on the WHEN-NEW-ITEM-INSTANCE trigger) simply replaces its trigger text with the trigger text of the POST-QUERY trigger. Thus, Forms has not recognized that a POST-QUERY trigger doesn't make sense at the item level and fails to understand that WHEN-NEW-ITEM-INSTANCE and POST-QUERY are two incompatible triggers.
- Smart classes do not support true multiple inheritance; that is, a given smart class cannot be based on two other independent smart classes. This is true even in the case of nested inheritance.
- An object cannot be smart-classed from two independent smart classes and in this way lacks multiple inheritance.
Only those smart classes corresponding to the given object type are displayed in the Smart Classes list when applying a smart class to an existing object, whereas any object that makes sense for the given object can be its subclass. For example, when applying a smart class for a block object, a Property Class Smart Class is not shown in the list, even though applying a property class to a block makes sense, whereas the same property class can be made subclass for the block without using the smart class. This overrides the extra smartness of smart classes.
Form libraries enable sharing of common code. Here are some tips for using form libraries:
- Data variables can be shared at runtime using packages in form libraries. When a library is attached to two or more forms in a multiform application, the parameter data_mode of CALL_FORM, NEW_FORM, and OPEN_FORM specifies whether to share common library data at runtime. Valid values for this property are the Forms constants NO_SHARE_LIBRARY_DATA and SHARE_LIBRARY_DATA.
- If changes are made to the library, it need not be detached and reattached. Forms automatically checks and updates references to these changes.
- A library's program units are loaded dynamically into an application only when needed.
- Stick to indirect referencing of form variables (that is, data- bearing items, system variables, and global variables) inside form library program units. This can be achieved by using the built-in COPY for assignment and NAME_IN for reading a variable value.