PocketBuilder techniques

PocketBuilder provides full support for inheritance, encapsulation, and polymorphism in both visual and nonvisual objects.

NoteCreating reusable objects In most cases, the person developing reusable objects is not the same person using the objects in applications. This discussion describes defining and creating reusable objects. It does not discuss usage.

Implementing inheritance

PocketBuilder makes it easy to create descendent objects. You implement inheritance in PocketBuilder by using a painter to inherit from a specified ancestor object.

Example of ancestor service object One example of using inheritance in custom class user objects is creating an ancestor service object that performs basic services, and several descendent service objects. The descendent objects perform specialized services and also have access to the ancestor’s services:

Figure 1-1: Ancestor service object

The ancestor service object u _ base _ service includes the u _ modify and u _ describe services and has two descendent objects. The descendent u _ selection _ service includes two services, and the descendent u _ print _ service also has two services.

Example of virtual function in ancestor object Another example of using inheritance in custom class user objects is creating an ancestor object containing functions for all platforms and then creating descendent objects that perform platform-specific functions. In this case, the ancestor object contains a virtual function (uf_change_dir in this example) so that developers can create descendent objects using the ancestor’s datatype.

Figure 1-2: Virtual function in ancestor object

The ancestor object u  platform has three functions, uf file read, uf file write, and uf change dir. Uf change dir is a virtual function that appears in the two descendent objects, u platform win c e and u platform win 32, where it is defined to perform platform specific functions.

For more on virtual functions, see “Other techniques”.

Implementing encapsulation

Encapsulation allows you to insulate your object’s data, restricting access by declaring instance variables as private or protected. You can then write object functions to provide selective access to the instance variables.

One approach One approach to encapsulating processing and data is as follows:

Another approach Another approach to encapsulating processing and data is to provide a single entry point, in which the developer specifies the action to be performed:

Implementing polymorphism

Polymorphism means that functions with the same name behave differently depending on the referenced object. Although there is some discussion over an exact meaning for polymorphism, many people find it helpful to think of it as follows:

Operational polymorphism Separate, unrelated objects define functions with the same name. Each function performs the appropriate processing for its object type:

Figure 1-4: Operational polymorphism

Two user objects, u _ em and u _ mle, each include a function called o f _ Get Parent Window.

Inclusional polymorphism Various objects in an inheritance chain define functions with the same name but different arguments.

With inclusional polymorphism PocketBuilder determines which version of a function to execute, based on where the current object fits in the inheritance hierarchy. When the object is a descendant, PocketBuilder executes the descendent version of the function, overriding the ancestor version:

Figure 1-5: Inclusional polymorphism

At the top of the chain, the object u _ sort includes a function u f _ sort ( ). Farther down the chain, an object u _ sort _ dw also includes a function u f _ sort ( ) that overrides u _ sort dot u f _ sort.