Relative Object Name Access
The object access method described above is relative. An object handle is determined by an object’s name relative to the object that sent the message. The use of relative object addressing makes it possible to maintain proper encapsulation while at the same time providing an object access scheme that is easy to code and easy to maintain. Relative object addressing is an important part of the DataFlex object model and should be thoroughly understood.
Good object-oriented programming style states that an object should only need to know about objects that exist within its immediate environment or scope. An object can be aware of itself, its immediate children, its parents (ancestors), and other objects declared within the same neighborhood. If an object needs to communicate with an object that is “out of its reach,” your object message interface should be changed. For example, if an object needs to communicate with an object in another neighborhood, you should change your interface so that the object can send a message to the neighborhood's container object (which is within its scope). The container would then send a message to its child (which is in its scope).
The DataFlex object accessing method and neighborhoods allow you to directly access all objects that you should be able to access. When an object handle is requested, through either a move command (move oMyObj to hoMyObj) or as part of a message (Send MyMgs of oMyObj), the following steps are taken to find the named object and return its handle ID:
-
The object sending the message looks for a child object with the target name. If an object is found, the object’s handle is returned.
-
If the sending object belongs to an object neighborhood, then the list of reachable objects within the neighborhood is searched for an object with the target name. If an object is found, the object's handle is returned.
-
The object sending the message checks to see if there is a properly named sibling object. If found, a handle is returned. At this point, it is actually looking at the parent’s child objects.
-
The object sending the message will now look at all child objects belonging to its grandparent object (siblings of the parent). If found, the handle is returned.
-
This process of moving up to an ancestor object and checking all children continues until an object is found, or the outer-most parent is tested and the target is still not found, in which case a handle value of zero is returned. This delegation takes place regardless of whether the parent is in the sending object's neighborhood.
This means that an object’s scope consists of:
- Itself
- Its children
- Its neighborhood
- Its ancestors (parents, grandparents, etc.)
- All sibling objects of all ancestors.
Consider the following object structure:
Object
oArray1
is an Array
End_Object
Object
oArray2
is an Array
Object
oArray3
is an Array
End_Object
End_Object
Object
oPanel
is a Panel
Object
oContainer1
is a Container3d
Object
oButton1
is a Button
End_Object
Object
oButton2
is a Button
End_Object
End_Object
Object
oContainer2
is a Container3d
Object
oButton3
is a Button
End_Object
Object
oButton4
is a Button
End_Object
End_Object
End_Object
End_Object
Object oArray1 has no parents and no children. Therefore, it can send messages to itself and its siblings, oArray2 and oPanel. Similarly, oArray2 can send messages to itself and oArray1 and oPanel.
Object oPanel has children but no parents. Object oPanel is a neighborhood container (all panel objects are neighborhood containers). Therefore, it can send messages to itself, all objects nested within itself, oArray1, and oArray2, but not oArray3. All objects within oPanel belong to the same neighborhood and therefore can send messages to the same objects that are accessible by oPanel.
It is important that all objects within a particular neighborhood have unique object names. Name clashes within a particular neighborhood may result in the wrong objects being referenced.
Note that the oArray2 object contains an array object (oArray3). Object oArray3 is not accessible from any object except for oArray2. Similarly, none of the array objects may access objects nested within oPanel since they do not belong to oPanel's neighborhood.
Relative object access means that when you send messages to objects, you will always use the object’s relative name (e.g., oButton1). If the object is found, the object is in scope and your program is proper. If the object is not found, the object is out of scope and your program needs to be corrected.
This relative object access method is one of the cornerstones of the DataFlex Application Framework (which is discussed in other documents). This method is used to create views, create and connect data-dictionary object structures, and create nested data-entry objects that all properly and elegantly connect to the proper data-dictionary objects.