Skip to content

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.

Creating Dynamic Objects

The syntax for dynamically creating an object is:

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

Where:

  • {object-name} is a reference to an object that will receive the Create message.
  • {class-id} is the id of the class, which can be obtained by using the RefClass function:

    (RefClass(Class Name))
    
  • {object-handle} is a handle variable identifier that will receive a handle to the newly created object.

The Create method is passed a class-id. It creates an object based on the class-id and returns the newly 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.

Destroying Dynamic Objects

The syntax for dynamically destroying an object is:

Send Destroy [of {object-name}]

Where:

  • {object-name} is a reference to the object to be destroyed.

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: Basic Dynamic Object Usage

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: Using Object / End_Object Syntax

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 they are 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: Creating an XML Document

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 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.