Chapter 3 The Application Description Language
{ Viewer myViewer; myViewer.Forward.width = 40; } |
If an object member reference occurs in an expression, then the value is simply accessed. If an object reference occurs as an lvalue, that is as the target of an assignment, and the assignment appears in a method applied to the object itself, then a simple assignment is performed. Such assignments are called native. If, however, the object member reference occurs in a method applied to some other object, then the run-time system checks for a standard Set_name method in the class of the object whose member is the target of the assignment, with the member name as part of the selector and the value of the right side of the assignment as the argument.
Assignments that invoke Set_ methods are called foreign. If such a Set_ method is not found for a foreign assignment, then a standard assignment is applied.
For an example of native assignment, consider a class named Book that has an integer member called CurrentPage. If you call a NextPage method on an instance of the Book class, and the method contains the statement,
CurrentPage = CurrentPage + 1;
then, in effect, you increment CurrentPage without calling the Set_CurrentPage method. In contrast you use foreign assignment when assigning to members defined in bases. Thus, if class Dictionary inherits from Book, and a method of Dictionary contains an assignment to CurrentPage, this assignment invokes the Set_CurrentPage method, if it exists.
All classes possess a default SetAttributes method. This method takes one argument, a specially formatted list of lists, each of whose sublists consists of a pair of elements, a string member name, and a corresponding value. The SetAttributes message is handled by iterating over the argument list, and performing the appropriate foreign assignment for each member/value pair. You can use a SetAttributes message to set members in bases. You can override the SetAttributes method, but it is probably dangerous to do so. This feature is similar in intent to the X toolkit varargs style interface, and it simplifies the writing of special constructors (see Section 3.25, "Object Initialization" page 49).
XFbutton myButton; list buttonList = { { 'x, 50 }, { 'y, 50 }, { 'width, 200 }, { 'height, 100 } }; { 'SetAttributes, buttonList } => myButton; |
You can create a handle to an object or a variable using the (&) operator. You cannot, however, take the handle of an object member that possesses a Set_ method. You can access object members through a handle using the (->) operator. The (*) operator dereferences a handle, but it cannot be applied in such a way that it returns an inappropriate target for an assignment. For example, you cannot use it to return an object on the left hand side of an assignment.
{ Viewer myViewer; handle vwrPointer; vwrPointer = &myViewer; vwrPointer->Forward.width = 40; } |
Note that unlike C++ pointers, ADL handles are dynamically typed. The built-in function isKindOf() provides run-time type checking of handles (see Section 3.22, "Metaclass Operations" page 43).
The keyword parent is always a handle to the object that has the current object as a direct member. In a method, the current object is always the object on which the method is being invoked. In an initializor block, the current object is the one being initialized. If the current object was dynamically created using the new operator, then there is no parent. This case can be tested using another keyword, theHeap. For dynamically created objects, parent == theHeap.
Generated with Harlequin WebMaker