SAS Object-Oriented Programming Concepts |
SCL provides dot notation for directly accessing object attributes and for invoking methods instead of using the SEND and NOTIFY routines. Thus, dot notation provides a shortcut for invoking methods and for setting or querying attribute values. Using dot notation reduces typing and makes SCL programs easier to read.
Using dot notation enhances run-time performance if you declare the object used in the dot notation as an instance of a predefined class instead of declaring it as a generic object. The object's class definition is then known at compile time, enabling the SCL compiler to verify the method and to access attributes at that time. Moreover, since dot notation checks the method signature, it is the only way to access an overloaded method. SEND does not check method signatures. It executes the first name-matched method, and the program might halt if the method signature does not match.
Syntax |
The syntax for dot notation is as follows:
object.attribute
or
object.method(<arguments>)
specifies an object or an automatic system variable (for example, _SELF_). An object must be a component in a FRAME entry or a variable that is declared as an Object type in the SCL program. Automatic system variables like _SELF_ are declared internally as Object type, so they do not have to be declared explicitly as such in a program.
specifies an object attribute to assign or query. It can be of any data type, including Array. If the attribute is an array, use the following syntax to reference its elements:
object.attributeArray[i]
You can also use parentheses instead of brackets or braces when referencing the array elements. However, if you have declared the object as a generic object, the compiler interprets it as a method name rather than an attribute array. If you have declared a type for the object, and an attribute and method have the same name, the compiler still interprets the object as a method. To avoid this ambiguity, use brackets when referencing attribute array elements.
specifies the name of the method to invoke. If an object is declared with a specific class definition, the compiler can perform error checking on the object's method invocations.
If the object was declared as a generic object (with the OBJECT keyword), then the method lookup is deferred until run time. If there is no such method for the object, the program halts. If you declare the object with a specific definition, errors such as this are discovered at compile time instead of at run time.
are the arguments passed to the method. Enclose the arguments in parentheses. The parentheses are required whether or not the method needs any arguments.
You can use dot notation to specify parameters to methods. For example:
return-value = object.method (object.id);However, if you use dot notation to specify an update or output parameter, then SCL executes the _setAttributeValue method, which may produce side effects. See What Happens When Attribute Values Are Set or Queried for more information.
Some methods may be defined to return a value of any SCL type. You can access this returned value by specifying a variable in the left side of the dot notation. For example:
return-value = object.method (<arguments>);
or
if ( object.method (<arguments>) ) then ...
The return value's type defaults to Numeric if it is not explicitly declared. If the declared type does not match the returned type, and the method signature is known at compile time, the compiler returns an error. Otherwise, a data conversion might take place, or the program will halt at run time.
If you override an object's INIT method, you must call _SUPER._INIT before you can use dot notation to set attribute values or to make other method calls.
Dot notation is not available in the INPUT and PUT functions.
By default, your application halts execution if an error is detected in the dot notation that is used in the application. You can control this behavior with the HALTONDOTATTRIBUTE or NOHALTONDOTATTRIBUTE option in the CONTROL statement. See CONTROL for more information.
You can also use dot notation in nested form. For example,
value = object.attribute1.method1().attribute2;
is equivalent to the following:
dcl object object1 object2; object1 = object.attribute1; /* attribute1 in object is of OBJECT type */ object2 = object1.method1(); /* method1 in object1 returns an object */ value = object2.attribute2; /* assign the value of attribute2 in object2 to the variable 'value'. */
You can also specify the nested dot notation as an l-value. For example,
object.attribute1.method1().attribute2 = value;
is equivalent to the following:
dcl object object1 object2; object1 = object.attribute1; object2 = object1.method1(); object2.attribute2 = value; /* assume 'value' has been initialized. This would set attribute2 in object2 to the value */
Note: You cannot use nested dot notation inside SUBMIT blocks.
Examples |
An application window contains a text entry control named clientName. The following examples show how to use dot notation to invoke methods and to query and assign attribute values. For example, the following statement uses dot notation to invoke the _gray method of the control:
clientName._gray();
This is equivalent to
call send('clientName','_gray');
You can change the text color to blue, using dot notation to set the value of its textColor attribute:
name.textColor='blue';
You can also use dot notation to query the value of an attribute. For example:
color=clientName.textColor;
You can use dot notation in expressions. You can use a method in an expression only if the method can return a value via a RETURN statement in its definition. For example, suppose you create a setTable method, which is a public method and accepts an input character argument (the name of a SAS table). The method determines whether a SAS table exists and uses the RETURN statement to pass the return code from the EXIST function.
setTable: public method dsname:i:char(41) return=num; rc = exist(dsname, 'DATA'); return rc; endmethod;
Then you could use a statement like the following to perform actions that depend on the value that the setTable method returned.
if (obj.setTable('sasuser.houses')) then /* the table exists, perform an action */ else /* the table doesn't exist, */ /* perform another action */
The next example shows how to use dot notation with an object that you create in an SCL program. Suppose class X is saved in the entry X.SCL, and the INIT section is saved in the entry Y.SCL.
class x; public num n; m: public method n1: num n2: num return=num; dcl num r; r = n1 + n2; /* return sum of n1 and n2 */ return r; endmethod; m: public method c1: char c2:char return=char; dcl num s; /* concatenate c1 and c2 */ s = c1 || c2; return s; endmethod; endclass; init: dcl x xobj = _new_ x(); dcl num n; dcl string s; n = xobj.m(99,1); s = xobj.m("abc","def"); put n= s=; return;
If you compile and run Y.SCL, it produces
n=100 s=abcdef
What Happens When Attribute Values Are Set or Queried |
When you use dot notation to change or query an attribute value, SCL translates the statement to a _setAttributeValue method call (to change the value) or to a _getAttributeValue method call (to query the value). As a result, defining the attribute with a getCAM or setCAM method could produce side effects.
When you use dot notation to specify a parameter to a method, SCL executes the _setAttributeValue method if the parameter is an update or output parameter. SCL executes the _getAttributeValue method if the parameter is an input parameter. However, if the object is declared as a generic object or if the method does not have a signature, then all of the method's parameters are treated as update parameters. Therefore, SCL will execute the _setAttributeValue method even if the parameter is an input parameter, which could execute a setCAM method and send an event.
Note: If you use dot notation to access a class attribute, program execution halts if any error is detected while the _getAttributeValue or _setAttributeValue method is running. Explicitly invoking the _getAttributeValue or _setAttributeValue method allows the program to control the halt behavior. The _getAttributeValue or _setAttributeValue method also enables you to check the return code from the method. For example:
rc = obj._setAttributeValue (`abc'); if ( rc ) then do; /* error detected in the _setAttributeValue method */ ...more SCL statements... end;
When you use dot notation to set the value of an attribute, SCL follows these steps:
Verify that the type of the attribute matches the type of the value that is being set.
Check whether the attribute value is in the ValidValues list. If the ValidValues metadata is an SCL entry, it is executed first to get the list of values to check the attribute value against.
Run the setCAM method, if it is defined, which gives users a chance to perform additional validation and to process their own side effects.
Note: If the Editable metadata is set to No, the custom set method is not called (even if it was defined for the attribute).
Send the "attributeName Changed" event if the SendEvent metadata is set to Yes.
sends the "contents Updated" event if the attribute is specified in the object's contentsUpdatedAttributes attribute. This event notifies components in a model/view relationship that a key attribute has been changed.
Flow of Control for _setAttributeValue
When you use dot notation to query the value of an attribute, SCL follows these steps:
Execute the getCAM method to determine the attribute value, if a getCAM method has been defined.
Return the initial class value, if no attribute value has been set.
Flow of Control for _getAttributeValue
Copyright © 2009 by SAS Institute Inc., Cary, NC, USA. All rights reserved.