Previous Page | Next Page

SAS Component Language Dictionary

METHOD



Defines a method that can be called by the METHOD routine
Category: Modular Programming and Object Oriented

Syntax
Details
Calling and Executing Method Blocks
Scope of Method Block Variables
Passing Parameters to Method Blocks
Returning Modified Parameters to the Calling Routine
Returning a Value to the Calling Routine
Examples
Example 1: METHOD Statement Declarations
Example 2: Using the RETURN= Option
Example 3: Reference Array Whose Size Is Determined at Run Time
Example 4: Calling a Method
Example 5: Using the REST= Argument
Example 6: Parameter Scope and Method Variable Scope
See Also

Syntax

method-name-label:< method-access-scope > METHOD <argument-list> <OPTIONAL=argument-list> <ARGLIST=arg-list-id | REST=rest-list-id><RETURN=data-type>;

method-name-label

specifies the method name label, which can be up to 32 characters in length. Method labels have the same syntax as SCL labels.

CAUTION:
Leading underscores in method names typically identify methods that are supplied with the SAS System.

It is recommended that you do not define method names that have leading underscores unless the underscores are required. For example, you may need to create a new component that supports an interface, such as the staticStringList interface, that has methods that are defined with leading underscores.  [cautionend]

method-access-scope

species how the method can be accessed. If the method-access-scope is not provided, a method has PUBLIC scope. Method-access-scope is valid only for METHOD statements in a CLASS or USECLASS block.

PUBLIC

specifies that the method can be accessed by any SCL program.

PRIVATE

specifies that the method can be accessed only by methods in the same class in which the method is defined. Private methods are not inherited by subclasses of the class.

PROTECTED

specifies that the method can be accessed only by subclasses of the class in which the method is defined. Because a class can be considered a subclass of itself, a protected method can also be accessed from the class in which it is defined.

argument-list

list one or more sets of arguments, with each set specified as follows:var-list:<INPUT|UPDATE|OUTPUT>:data-type(length)

var-list

lists one or more variables to contain values that are passed in from a method call using either dot notation or the METHOD, SEND, SUPER, APPLY or SUPAPPLY routine or function. Variables can also be a reference array. Reference array's dimensions are specified by '*'. Comma delimiters are required to separate '*' for multiple dimensions. The actual size of the reference array will be determined at run-time based on the dimensions specified in the array parameter of the calling method. For more information, see ARRAY and the example Reference Array Whose Size Is Determined at Run Time.

INPUT | I

the values of the caller's parameters are copied into the corresponding parameters in the called method. When the called method's ENDMETHOD statement is executed, any updated values are not copied out to the caller's parameters. This is equivalent to using CALL NOCHANGE() inside the METHOD block.

UPDATE | U

the values of the caller's parameters are copied into the corresponding parameters in the called method. When the called method's ENDMETHOD statement is executed, any updated values are copied out to the caller's parameters (unless CALL NOCHANGE is specified). An error condition results if the corresponding parameter in the calling program is a constant, because a constant cannot receive a value. All Version 6 SCL method parameters are UPDATE parameters.

OUTPUT | O

this storage type serves as an indication in the code that only the returned value is significant, despite the fact that the input parameter might change. Functionally, the output type is the same as update type.

data-type

specifies the type of data that the variable will contain. A named data type (for example, CHAR or LIST) must be preceded by the : delimiter. The delimiter is optional for unnamed data types (for example, $).

CHAR<(length)>

specifies that the variable will contain character data. Length can be 1 to 32,767 characters. If length is not provided, the default length is 200.

Note:   You cannot specify length for the CHAR data-type within the RETURN option.  [cautionend]

LIST

specifies that the variable will contain an SCL list identifier.

NUM

specifies that the variable will contain a numeric value.

OBJECT

specifies that the variable will contain the identifier for an object when it is defined at run time.

This type causes the SCL compiler to generate extra conversion instructions. Consequently, you should use it only when necessary so as to achieve optimal run-time performance.

class-name

specifies that the variable will contain the identifier for an object of the class specified in class-name. This type of object is defined at compile time. Class-name must be a three- or four-level name unless an IMPORT statement has specified the libref and catalog. In that case, the name can be a one- to four-level name. If the entry type is not specified, it is assumed to be CLASS.

interface-name

specifies that the variable will contain the identifier for an object of the class that supports the interface specified in interface-name. Interface-name must be a three- or four-level name unless an IMPORT statement has been used to specify the libref and catalog. In that case, the name can be a one- to four-level name.

If the entry type is not specified and a class with that name does not exist, the default entry type of INTERFACE is assumed.

To be compatible with the applications built in earlier releases of SAS software, the : delimiter is optional for variables that are declared with unnamed data types (for example, $), but it is required for variables that are assigned named data types. The following example shows a variety of data type declarations including the reference arrays using * as the dimensions:
mymethod: method
   char1  : Char(20)
   char2  : Char(10)
   char3  :input :char(50)
   charArr(*):u:char /* a reference array */
   num1   : Num
   num2   : Num
   num3   : num
   numArr(*):num     /* a reference array */
   myList :list
   myObj  :object
   myCol :sashelp.fsp.Collection.class ;

Type: Character

length

is a numeric constant that specifies the length of the preceding variable or variables. The length of a character variable does not have to match the length of the corresponding passed parameter. SCL pads or truncates as necessary. When a length is specified for a variable that is declared as CHAR, the length specification must be enclosed in parentheses.

Type: Character

arg-list-id

contains the identifier for the SCL list that will contain all the arguments passed to the method. This includes all optional arguments.

Type: List

rest-list-id

contains the identifier for the SCL list that will contain all arguments that are passed to the method but are not explicitly specified in argument-list for either METHOD or OPTIONAL=.

Type: List

data-type

specifies the type of data that the method can return. The valid data types are Num, Char, List , Object , Array, and Class types.


Details

The METHOD statement enables you to create method blocks and methods for SAS/AF classes. A method block is a feature for defining methods or for making a frequently used routine available to other programs. Methods define the actions for a class. A method block starts with the METHOD labels and ends with an ENDMETHOD statement. Only SCL entries can contain method blocks. Each method block contains additional SCL statements.

RETURN=data-type enables you to return a value to the calling method. An error condition is produced if data-type is not the same as the type of data to be returned to the calling program. Use a RETURN statement in the method to specify the value to return.

In SCL CLASS statement block or USECLASS statement block, each METHOD statement starts a new local variable scope just like an SCL DO/END block. Parameters with the same name but with the different types can be used across different method statements.

The METHOD statement receives parameters from the calling routine. When there are no optional arguments in the METHOD statement, a strict correspondence is required between the parameters that are passed by the calling routine and the arguments for the METHOD statement. The arguments and parameters must agree in number, data type, and relative position. If the calling program passes an incorrect number of parameters or a parameter of an incorrect type, SCL stops executing the program. The argument-parameter correspondence is less restrictive when you use the options OPTIONAL=, ARGLIST=, and REST= in the METHOD statement:

OPTIONAL=

enables you to specify one or more optional arguments that are used only if the calling program supplies the corresponding parameters in the parameter list of the calling routine. If corresponding parameters are not supplied, then the optional arguments are initialized to missing values.

ARGLIST= and REST=

enable you to pass a variable number of parameters to the METHOD statement. You determine the types and order of the variable arguments. The lists identified by arg-list-id and rest-list-id are created automatically when the entry is called, and they are deleted automatically when the entry ends. When an array is passed as a parameter, the array is expanded into individual items and these items are inserted into the arg-list-id and rest-list-id lists. ARGLIST= and REST= are mutually exclusive, so you can use only one or the other.


Calling and Executing Method Blocks

Other SCL programs call a method block by specifying its label in a dot notation statement or in a METHOD, APPLY, SUPER, SUPAPPLY, or SEND routine or function. Execution of the method block starts at the METHOD statement and ends with the ENDMETHOD statement. After a method block is executed, control returns either to the calling program statement or to the command line. A method block can be tested individually by invoking a TESTAF command with the label=method-name option with the SCL debugger. For example, the following statement tests the COMBINE method:

testaf label=combine


Scope of Method Block Variables

All variables that are declared using the DECLARE statement in a method block are local to that method. You cannot use a GOTO statement to jump into a method block in the current entry. All the method parameters are also local to that method if method blocks are written inside a CLASS statement block or a USECLASS statement block.


Passing Parameters to Method Blocks

The METHOD statement can receive parameter values for variables that are declared as UPDATE or INPUT. By default, all parameters declared in a METHOD statement are UPDATE parameters.

The parameter-receiving mechanism for the METHOD statement is very similar to that mechanism for the ENTRY statement. The METHOD statement receives parameters from the third argument of the calling METHOD routine. The calling METHOD routine must agree with the corresponding METHOD statement in the following ways (unless OPTIONAL=, ARGLIST=, or REST= are specified):

Otherwise, SCL stops executing the calling METHOD routine and prints an error message.


Returning Modified Parameters to the Calling Routine

The METHOD statement can return values to parameters from variables that are declared as UPDATE or OUTPUT. A called method block can modify any argument it receives. However, it cannot return new values to calling routine parameters that are numeric literals, character literals, or expressions. By default, values for variables are returned to the calling routine. If you want a called method block to receive values but not to return values to its calling routine, declare the variables as INPUT. If you want variables in the method to only return values, then declare the method's variables as OUTPUT.

For more information, see What Happens When Attribute Values Are Set or Queried.


Returning a Value to the Calling Routine

A METHOD statement can return a value to the calling routine when the METHOD statement uses the RETURN= option to declare the data type of the returned value. A RETURN statement in the method specifies either the variable or expression that contains the value or the literal value to return.


Examples


Example 1: METHOD Statement Declarations

Method M1 contains a variety of argument specifications.

IMPORT work.myclass.collection.class;
Class Example1;
M1: PUBLIC  METHOD
       /* usenum is UPDATE (default) numeric    */
    usenum :NUM
       /* usechar is UPDATE (default) character */
    usechar :CHAR
       /* mylist is UPDATE (default) list       */
    mylist :LIST
       /* myobject is UPDATE (default) object   */
    myobject :OBJECT
       /* mycoll is UPDATE (default) collection */
    mycoll :COLLECTION
       /* innum is INPUT  numeric               */
    innum :INPUT :NUM
       /* state is OUTPUT character             */
    state :OUTPUT :CHAR
       /* namelist is UPDATE list               */
    namelist :UPDATE :LIST
       /* outputobj is OUTPUT object            */
    outputobj :OUTPUT :OBJECT
       /* amountin is INPUT  numeric            */
    amountin :I :NUM
       /* c3 is OUTPUT character                */
    c3 :O :CHAR
       /* l3 is UPDATE list                     */
    l3 :U :LIST
       /* numarr is a numeric UPDATE array      */
    numarr(5) : NUM
       /* states is a character reference array */
    states(*) : CHAR
       /* return a numeric value                */
    RETURN=NUM;

    ...SCL statements that define the method...
    RETURN(0);

ENDMETHOD;
EndClass;


Example 2: Using the RETURN= Option

Define an ADD method to add the numbers stored in N1 and N2, and return the sum in the variable TOTAL:

Class Example2;
add: public method n1:num n2:num return=num;
   total=n1+n2;
   return(total);
endmethod;
EndClass;


Example 3: Reference Array Whose Size Is Determined at Run Time

The following Sort class contains two overloaded methods that are named SORT. Each method contains an array parameter that is a reference array. The size of the reference array will be determined at run time based on the associated array parameters in the calling methods.

Class Sort;
/* Generic sort routine for any size of */
/* 1-dimensional numeric array */
sort: method narr(*):Num;
    /* Find dimensions from the calling program */
    DCL Num temp i j;
    DCL Num size = dim(narr);
    /* --- Bubble Sort --- */
    do i = 1 to size - 1;
	do j = i+1 to size;
	    if narr(i) > narr(j) then
	    do;
		temp = narr(i);
		narr(i) = narr(j);
		narr(j) = temp;
	    end;
	end;
    end;
    /* Array narr is now sorted in ascending order */
endmethod;

/* Generic sort routine for any size of */
/* 1-dimensional character array */
sort: method carr(*):Char;
    /* Find dimensions from the calling program */
    DCL Char tempc;
    DCL Num  i j size = dim(carr);
    /* --- Bubble Sort --- */
    do i = 1 to size - 1;
	do j = i+1 to size;
	    if carr(i) > carr(j) then
	    do;
		tempc = carr(i);
		carr(i) = carr(j);
		carr(j) = tempc;
	    end;
	end;
    end;
    /* Array carr is now sorted in ascending order */
endmethod;
EndClass;


Example 4: Calling a Method

This example creates a new instance of the Sort class and sends a message to the sort method to sort the order of the existing arrays CARR and NARR.

Init:
  DCL Char(20) carr(3)=('c','b','a');
  DCL Num narr(3)={3, 2, 1};
  DCL Sort obj1 = _NEW_ Sort(narr);
  DCL Sort obj2 = _NEW_ Sort(carr);
  put carr= narr=;
return;

The output is

carr=
carr[1]='a'
carr[2]='b'
carr[3]='c'
narr[1] = 1
narr[2] = 2
narr[3] = 3


Example 5: Using the REST= Argument

Add a variable number of numbers, and print out the sum. The method ignores any character types that are passed in.

   class varying;
        sumPrint: method msg:Char rest=rest_list/(signature='N');
       DCL num totsum i,
           char(1) type;
       if rest_list=. then
       do;
          put 'No numbers to add were passed in!';
          return;
       end;
       totsum=0;
       do i=1 to listlen(rest_list);
          type=itemtype(rest_list,i);
          if type='N' then
          do;
             valn=getitemn(rest_list,i);
             totsum=totsum+valn;
          end;
       end;
       put msg totsum;
       endmethod;
    endclass;

Use the following program to invoke the SUMPRINT method:

Init:
   DCL varying obj = _NEW_ Varying();
   obj.SUMPRINT('The total is:', 15, 30, 1);

The output of this example is

The total is: 46


Example 6: Parameter Scope and Method Variable Scope

This program shows the parameters of the same name and different types being used across different method statements.

Class ReUseName;
   m1: Method n:Num c:Char;
        DCL  Num  localN;
        DCL  Char localC;
       EndMethod;
   m2: Method n:Char c:num;
        DCL Char localN;
        DCL Num  localC;
       EndMethod;
EndClass;


See Also

IMPORT

Previous Page | Next Page | Top of Page