Dynamic Objects

Typically objects are created when an Object / End_Object command block is executed. Once created, those objects exist until the program terminates (unless explicitly destroyed).

Under some conditions, you may wish to create and destroy objects dynamically. Dynamic object creation and destruction is typically performed inside of methods (procedures and functions) that need to temporarily create an object, work with it, and then dispose of it when no longer needed. For example, this type of dynamic object management is used extensively when parsing XML documents.  Two methods are used to handle dynamic objects: Create and Destroy.

Object Creation

The syntax for dynamically creating an object is:

Get Create [of {object-name}] {class-id} to {object-handle}

Where:

(RefClass(Class Name))

The Create method is passed a class-id. It creates an object based on the class-id and returns the new created object's handle. The object is created as a child of the object that receives the Create message.

The Create method returns a handle to the object. During the lifetime of the object, it will be referenced by its handle. Dynamically created objects do not have meaningful names.

Object Destruction

The syntax for dynamically destroying an object is:

Send Destroy [of {object-name}]

Where:

The Destroy message destroys the object that receives the message. It also destroys any child objects contained within the object. When an object is destroyed, all resources used by the object are freed. The Destroy message can be used to destroy any object, but is used most frequently to destroy dynamically created objects.

Dynamically created objects should be destroyed when they are no longer needed or they will remain in memory until the program terminates. Dynamically created objects should be destroyed in reverse order of their creation.

Example

This example creates a cObject object, uses it, and then destroys it.

Procedure ProcessData

    Handle hoData

 

    Get Create (RefClass(cObject)) to hoData

 

    Send DoLoadData hoData

    Send DoUpdateData hoData

    Send Destroy of hoData

End_Procedure

Example

This example could also have been coded using the Object / End_Object syntax as follows:

Procedure ProcessData

    Handle hoData

 

    Object oTempObject is a cObject

        Move Self to hoData

    End_Object

 

    Send DoLoadData hoData

    Send DoUpdateData hoData

    Send Destroy of hoData

End_Procedure

One limitation of this syntax is that the temporary object can only be a child of the current object, while using the Create method, the temporary object can be a child of any object:

Create (RefClass(SomeClass)) of oSomeParent to hoSomeChild

There are ways to achieve this using the Object / End_Object method, but not as straightforward.

Typically, dynamic objects are created using the Create method. This method is more convenient than the Object / End_Object method if you just need an anonymous object that will be discarded when the current method exits.

You can assign an object name to an object created using the Create method, which can be useful in aiding debugging, but the object cannot be addressed using that name:

Get Create (RefClass(Class)) to ohId

Set Name of ohId to "oName"

Example

The following example shows a more complicated example of working with dynamic objects to create an XML document.

Function CustomerXMLList Returns XmlHandle

   Integer bOk

   Handle hoXML hoRoot hoEle hoCustomerDD

   String sName sNumber sState sNamespace

 

   Move Customer_dd to hoCustomerDD

   // namespace to use for document

   Move "http://www.dataaccess.com/Test/CustomerList" to sNameSpace

   // create XML document / Create root node

   Get Create (RefClass(cXMLDomDocument)) to hoXML

   // Create the Root element named CustomerList

   Get CreateDocumentElementNS of hoXML sNameSpace "CustomerList" to hoRoot

 

   // now loop through all customer records

   //Send AddAttribute of hoRoot "xmlns:m" sNameSpace

   Send Clear of hoCustomerDD

   Send Find of hoCustomerDD ge 2

   While (Found)

       // get name, number and state to strings

       Move (trim(Customer.Name)) to sName

       Move Customer.Customer_Number to sNumber

       Move (trim(Customer.State)) to sState

       // for each customer create customer node with child elements

       Get AddElementNS Of hoRoot sNameSpace "Customer" "" to hoEle

          Send AddElementNS of hoEle sNameSpace "Name" sName

          Send AddElementNS of hoEle sNameSpace "Number" sNumber

          Send AddElementNS of hoEle sNameSpace "State" sState

          Send AddAttributeNS of hoEle sNameSpace "num" 1

       Send Destroy of hoEle

       Send Find of hoCustomerDD gt 2

   Loop

 

   Function_Return hoXML

End_Function

Dynamic object creation can be used to create non-visual and visual objects. Most often it is used with non-visual objects.