space
Previous Page | Next Page

SAS Object-Oriented Programming Concepts

Methods

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.  [cautionend]


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:

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

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:

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 0-255). 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,


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.  [cautionend]

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.  [cautionend]

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.

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.

space
Previous Page | Next Page | Top of Page