Methods

Introduction

In a SAS/AF software class, methods define the operations that can be executed by any component you create from that class. In other words, methods are how classes (and instances of those classes) do their work.
A method consists of two primary parts, its name and its implementation. You use the method name in SCL programs to manipulate the associated component. For example, to deselect the selections in a list box, you write an SCL statement that invokes the _deselectAll method:
listbox1._deselectAll();
Use caution when adding new methods with a leading underscore character, which typically indicates a method supplied by SAS and may cause conflicts with future releases of SAS/AF software. If you attempt to name a method with both leading and trailing underscores, SAS/AF displays a warning. Embedded underscores themselves are allowed, but they are removed when a leading and trailing underscore trigger the name conversion. For example, the method name _foo_Test_Foo is converted to _fooTestFoo.
Method names can be up to 256 characters long.
The implementation of the method (where the code exists) is specified in the name of a SAS/AF entry. This entry is usually an SCL entry that is combined with an optional SCL labeled section.
As previously mentioned, all classes inherit methods from their parent classes. Some classes also delegate methods to other classes. In addition, SAS/AF software defines three other types of methods:
automatic methods
are methods that automatically execute when certain events occur; you do not explicitly call automatic methods. Automatic methods can be classified in two major groups:
  • those that execute at build time — for example, _bInit.
  • those that execute at run time (that is, when the FRAME entry is opened by a TESTAF, AF, or AFA command) — for example, _select.
For more information about automatic methods, see Flow of Control for Frame SCL Entries.
virtual methods
are methods that exist in a class but have no defined functionality for that class. You add their functionality by overriding the method in a subclass. Virtual methods exist for these reasons:
  • The functionality of the method needs to be defined, but its functionality is specific to the subclass.
  • The presence of a virtual method serves as a reminder that the method should be included in the subclass and that its functionality should be defined there.
The Object class contains some virtual methods — for example, _printObject. Each object can have specific printing needs; therefore, you should define the functionality of _printObject at the subclass level. Unless you override the definition of _printObject, the method does nothing, but it also does not generate an error.
per-instance methods
are methods that enable you to add to or override a method for a specific object in an application. These methods are not associated with a class but are assigned on a per instance basis. A per-instance method that is bound to an object is not shared with or available to other instances of the object's class. Per-instance methods do not affect any other objects in the application.
All predefined methods for a class are listed in the class's methods list. When a method is called, the SCL compiler searches the object class's methods list for the method. If no matching method is found there, the compiler searches the class's parent class, and so on. If an object has per-instance methods, the method lookup begins in the object's list of per-instance methods.
Per-instance methods are programmatically added, changed, and deleted with these Object Class methods:
  • _addMethod
  • _changeMethod
  • _deleteMethod
For more information about these methods, see the Object class in the Component Reference section of the SAS/AF online Help.
Note: Although supported, per-instance methods represent a non-object-oriented approach to SAS/AF programming. A side effect of this approach is that the compiler cannot identify per-instance methods or attributes that have been added programmatically via SCL. Only those per-instance methods and attributes that have been added through the Properties window are recognized at compile time.

Method Signatures

A method's signature uniquely identifies it to the SCL compiler. A method's signature is comprised of the method's name, its arguments, and their types and order. Precise identification of a method based on these parameters is necessary when overloaded methods are used (see Overloading Methods).
For example, the following SCL METHOD statements show methods that have different signatures:
Method1: method name:char  number:num; endmethod;
Method2: method number:num name:char;  endmethod;
Method3: method name:char;             endmethod; 
Method4: method return=num;            endmethod;
Each method signature is a unique combination, varying by argument number and type:
  • The first signature contains a character argument and a numeric argument.
  • The second signature contains a numeric argument and a character argument.
  • The third signature contains a single character argument.
  • The fourth signature contains no arguments.
Signatures in SAS/AF software are usually represented by a shorthand notation, called a sigstring. This sigstring is stored in the method metadata as SIGSTRING. For example, the four method statements above have the following sigstrings:
Method1 sigstring: (CN)V
Method2 sigstring: (NC)V
Method3 sigstring: (C)V
Method4 sigstring: ()N
The parentheses group the arguments and indicate the type of each argument. The value outside the parentheses represents the return argument. The V character (for “void”) indicates that no return value is used. A notation that has a value other than V indicates that the signature has a return value of that particular type. For example, Method4, above, returns a numeric value.
Although the optional return variable is listed as part of the sigstring, it is listed only for convenience and should not be understood as part of the actual signature. In a sigstring, neither the presence of a return variable nor its type affects the method signature.
When a method is called, the SAS SCL compiler matches the arguments in the call to the arguments in the actual method. Thus, calling the method with the (CN)V signature actually executes Method1, below. Calling the method with the (NC)V arguments executes Method2:
/* Method1 */
/* Responds to calls using the (CN)V signature */
  object.setColNum('colname', num);

/* Method2 */
/* Responds to calls using the (NC)V signature */
  object.setColNum(num, 'colname');
If a method has a return value, you can execute that method and use the value that it returns in an assignment. For example, consider an object that has a method with a signature ()N. The following are valid operations:
dcl num returnVal;
returnVal=object.getData();
or
if object.getData() > 1 then do ...
or
if ( object.getData() ) then do ...
Defining signatures for methods helps other developers understand the method syntax while also offering enhanced compile-time checking and run-time efficiency. The default signature for methods is ()V, meaning that no arguments are passed into the method and no values are returned.
Although the SCL compiler uses the method name to help uniquely identify a method, the name is not formally part of the signature metadata. In other words, although a method's signature includes its name and arguments (and their types and order), the signature metadata itself consists of
  • argument name
  • argument type
  • argument usage
  • argument description
Just like return variables, the usage and description of an argument are not used to differentiate methods, and are not part of a method's signature, even though they are part of the signature metadata.
Once you define a signature for a method and deploy the class that contains it for public use, you should not alter the signature of the method in future versions of the class. Doing so could result in program halts for users who have already compiled their applications. Instead of altering an existing signature, you should overload the method to use the desired signature, leaving the previous signature intact.

Overloading Methods

SAS Component Language (SCL) supports method overloading, which means that a class can have methods of the same name as long as they can be distinguished on the basis of their signatures (that is, as long as their arguments differ in number, order, and/or type). If you call an overloaded method, SCL checks the method arguments, scans the signatures for a match, and executes the appropriate code.
For example, if you had a setColor method on your class, you could define overloaded methods with the following signatures:
Overloaded setColor Methods
Method Calling Statement
Method Signature
object.setColor(color);
(C)
object.setColor(r, g, b);
(NNN)
In the example above, color is a character argument, and r, g, and b are numeric arguments. Both methods change the object's color even though the first method takes a color name as input and the second method takes numerical RGB values (in the range of 0255). The advantage of overloaded methods is that they require programmers to remember only one method instead of several different methods that perform the same function with different data.
Methods in general, not just overloaded methods, can specify only one return argument. Each method in a set of overloaded methods can have a different return argument type, but the method parameters must be different for each method since the return type is not considered part of the signature. For example, you can have
mymethod (NN)V
mymethod (CC)N
but not
mymethod (NC)V
mymethod (NC)N
The order of arguments also determines the method signature. For example, the getColNum methods below have different signatures — (CN)V and (NC)V — because the arguments are reversed. As a result, they are invoked differently, but they return the same result.
/* method1 */
getColNum: method colname:char number:update:num;
  number = getnitemn(listid, colname, 1, 1, 0);
endmethod;

/* method2 */
getColNum: method number:update:num colname:char;
  number = getnitemn(listid, colname, 1, 1, 0);
endmethod;
Each method in a set of overloaded methods can have a different scope, as well. However, the scope is not considered part of the signature (just as the return value is not), so you may not define two signatures that differ only by scope. (See the next section, “Method Scope”.)
In addition, a method that has no signature (that is, which has (none) as a signature) cannot be overloaded.

Method Scope

SAS Component Language (SCL) supports variable method scope, which gives you considerable design flexibility. Method scope can be defined as Public, Protected, or Private. The default scope is Public. Only Public methods appear in the Properties window at design time. In order of narrowing scope:
  • Public methods can be accessed by any other class and are inherited by subclasses.
  • Protected methods can be accessed only by the same class and its subclasses; they are inherited by subclasses.
  • Private methods can be accessed only by the same class and are not inherited by subclasses.

Method Metadata

In addition to a method's name, implementation, signature, and scope, SAS/AF software stores other method metadata for maintaining and executing methods. You can query a class (or a method within a class) to view the method metadata, and you can create your own metadata list to add or change a method. For example, to list the metadata for a particular method, execute code similar to the following:
init:
   DCL num rc metadata;
   DCL object obj;
   obj=loadclass('sashelp.mycat.maxClass.class');

   /* metadata is a numeric list identifier */
   rc=obj._getMethod('getMaxNum',metadata);
   call putlist(metadata,'',2);
return;
Here is the returned method metadata:
(NAME='getMaxNum'
 SIGNATURE=(   
   NUM1=(   TYPE='Numeric'
            INOUT='Input'
            DESCRIPTION='First number to compare'
   )
   NUM2=(   TYPE='Numeric'
            INOUT='Input'
            DESCRIPTION='Second number to compare'
   )
   RETURN=(   TYPE='Numeric'
              DESCRIPTION='Returns the greater of two numeric values.'
              INOUT='Return'
   )
 )
 SIGSTRING='(NN)N'
 ENTRY='sasuser.mycat.maxClass.scl'
 LABEL='getMaxNum'
 CLASS=4317
 METHODID=4331
 STATE='N'
 DESCRIPTION='Returns the greater of two numeric values.'
 ENABLED='Yes'
 SCOPE='Public'
)
The method metadata contains the following named items:
Note: Because many methods are defined at the C code level, some metadata values, such as Entry, may not provide information that you can use.
Name
is the name of the method. Method names can be up to 256 characters long.
State
specifies whether the method is new (N), inherited (I) from another class, overridden (O), or a system (S) method.
Entry
is the name of the SAS/AF catalog entry that contains the method implementation. Typically, this item is an SCL entry.
Example: sasuser.app.methods.scl
Label
is the name of the SCL labeled section where the method is implemented. This item is valid only if the value of the Entry metadata item is an SCL entry. A typical implementation of a method may look like the following:
Example: newMethod
newMethod: public method
     item:input:num
     return=num;
     /* ...more statements... */ 
endmethod;
Signature
is a list of sublists that correspond to the arguments in the method signature.
If an empty list is passed for this value, then SAS/AF software registers a signature of ()V, which means that the signature contains no arguments. If you call a method whose signature is ()V and specify any input, output, or return arguments, the compiler reports an error.
If a missing value (.) or zero is passed for this value, then the method does not have a stored signature. There is no compile-time checking for methods that have no stored signature. Likewise, if a method does not have a signature (the signature is (none)), it cannot be overloaded (although it may still be overridden). See Overloading Methods for more information.
Note: By default, legacy classes do not have signatures.
For each argument in a method signature, the following named items are stored in a sublist that has the same name as the argument:
Type
is the argument type. Valid values are
  • Character
  • Numeric
  • List
  • Object (generic)
  • Class Name (a four-level name of a specific object)
  • an array of any valid type
Type is the argument type. Valid values are
INOUT determines how the argument will be used in the method. Valid values are I | O | U | R (corresponding to Input, Output, Update, Return).
Description is a text description of the argument.
Return_MethodID is the unique identifier of the method; it is assigned when the method is created and is returned in this named item.
Scope
specifies which classes have permission to execute the method. Valid values are Public | Protected | Private. The default scope is Public.
If Scope='Public', then any class can call the method. The method is displayed in the component's Properties window at build time.
If Scope='Protected', then only the class and any subclasses can call the method. The method does not appear in the component's Properties window at build time, nor can you access the method via frame SCL.
If Scope='Private', then only the class itself can call the method. The method does not appear in the component's Properties window at build time, nor can you access the method via frame SCL.
Enabled
determines whether a method can be executed. Valid values are 'Yes' | 'No.' The default value is 'Yes.'
Description
is a description of the method.