Creating a Class with SCL

Introduction

As an alternative to creating a class interactively with the Class Editor, you can create a SAS/AF class entirely in SCL with the CLASS/ENDCLASS statement block. You can define all property information through SCL. When you have finished defining a class with SCL, you must save it as a CLASS entry so that it can be used as a class.
Creating a class with SCL has several advantages:
  • Lengthy or repetitive changes to class information (such as adding or deleting the signatures for several methods) are easier with a text editor than with the interactive, graphical approach of the Class Editor.
  • Classes that are defined in an SCL entry can define and implement methods in one location.
  • The CLASS block provides improved error detection at compile time, as well as improved run-time performance.
Metadata information, such as description, is added to the class or property by including a forward slash (/) delimiter and the appropriate metadata items enclosed in parentheses before the semicolon (;) that ends the statement. Use a comma to separate multiple metadata items (see description, SCL, and Label in the definition of the add method below).
Consider the following example, which defines the Combination class in SCL:
CLASS sasuser.myclasses.Combination.class
   extends sashelp.fsp.Object.class
   / (description='My Combination Class');

   /* define attributes */
   Public num total
   / (description='total attribute');
   Public char catstr
   / (description='catstr attribute');

   /* define methods    */
   add: public method
      n1: num
      n2: num
      return=num
      /(description='Adds two numbers',
        SCL='sasuser.myclasses.Combination.scl',
        Label='add');
   concat: public method
      c1: char
      c2: char
      return=char
      /(description='Concatenates two strings',
        SCL='sasuser.myclasses.Combination.scl',
        Label='concat');
ENDCLASS;
To compile the SCL program and save it as a CLASS entry:
  1. Save the SCL entry. You must save an SCL entry before using Save as Class or the SAVECLASS command.
  2. From the Source window, selectFilethen selectSave As Class.
    Alternatively, you can enter the SAVECLASS command.
Saving an SCL program as a class is equivalent to saving a class that you created interactively with the Class Editor.
You can implement the methods directly in the same SCL as the class definition. The following code defines the Combination class and implements its methods:
CLASS
sasuser.myclasses.Combination.class
   extends sashelp.fsp.Object.class
   / (description='My Combination Class');

   /* define attributes */
   Public num total
   / (description='total attribute');
   Public char catstr
   / (description='catstr attribute');

   /* define methods    */
   add: public method
      n1:num
      n2:num
      return=num
      /(description='Adds two numbers');
      total=n1+n2;
      return (total);
   concat: public method
      c1:char
      c2:char
      return=char
      /(description='Concatenates two strings');
      catstr=c1 || c2;
      return(catstr);
ENDCLASS;
Additionally, you can create an abstract class by adding the optional reserved word ABSTRACT before the CLASS statement. For example:
ABSTRACT CLASS myClass
   EXTENDS sashelp.fsp.Object.class;
   /* ...insert additional SCL here... */
ENDCLASS;
For complete information about the CLASS statement, including all valid metadata that you can include with the class and properties definitions, see the SAS Component Language: Reference.

Converting a Class to an SCL Entry

You can convert any SAS/AF class to an SCL entry. This enables you to view and extend a class directly through its SCL. There are two ways to convert a class to SCL:
  • You can use the Class Editor to save a class as an SCL entry by selecting Filethen selectSave As and setting the Entry Type to SCL. After saving the class as SCL, open the SCL entry to view or modify the class.
  • You can programmatically convert classes to SCL using the CREATESCL function. The following code is an example of the CREATESCL syntax:
    rc = CreateSCL ('lib.cat.yourClass.class',
                   'lib.cat.yourSCL.scl','description');
    In this example, lib.cat.yourClass.class is the class to convert, lib.cat.yourSCL.scl is the SCL entry to be created, and description contains the description of the class that is stored in the SCL entry.

Tips for Creating Classes with SCL

When you create a class using SCL, there are several recommended practices that might help your development efforts:
  • For components that might be edited in the Class Editor, it is more appropriate to create one SCL entry for the class definition and another for the method implementations of that class. Method implementations are not stored with a CLASS entry. If you use the Class Editor to save a class as an SCL entry, and if the original CLASS entry was created from an SCL entry that contained method implementations, you may overwrite the method implementations for that class.
  • It is recommended that you implement a standard naming convention for the catalog entries that are used to create a class. Since methods for a class are most often implemented in an SCL entry that has the same name as the CLASS entry, you might consider consistently appending “class” to the name of the SCL entry that defines the class. For example, consider a class named Document that was created using SCL and whose methods are implemented in a separate catalog entry. There would be a total of three entries:
    • the SCL entry that defines the class (sasuser.myclasses.Documentclass.scl)
    • the SCL entry that implements the methods of the class (sasuser.myclasses.Document.scl)
    • the class entry itself (sasuser.myclasses.Document.class).
  • Add values for the descriptive method-definition metadata, including Description and all argument descriptions (such as ArgDesc1 or ReturnDesc). For example, consider the descriptive metadata for a method named getAmount that has a signature (C)N:
    getAmount: public method
       account:input:char
       return=num
       /(Description='Returns the amount in the specified account',
         ArgDesc1='Account to retrieve',
         ReturnDesc='Amount in the account');
    In this example, Description is the description of the method, ArgDesc1 is the description of the account argument, and ReturnDesc is the description of the return argument.
    For complete information, refer to the CLASS statement in the SAS Component Language: Reference.

Implementing Methods Using CLASS and USECLASS Statement Blocks

Introduction

The CLASS and USECLASS statements can be used to implement methods for a class in SCL and to bind them to the class at compile time, which improves code readability, code maintainability, run-time performance, and compile-time detection of many types of errors. SCL users can directly reference attributes and methods in a CLASS or USECLASS block without specifying the object ID or the system variable _SELF_. The CLASS statement is used both for defining and for implementing methods. The USECLASS statement is used only for implementing methods.

CLASS Statement

The CLASS statement constructs a class with SCL code, including the class definitions and, optionally, the method implementations. The ENDCLASS statement ends the CLASS statement block. In the following example, the method implementation is coded inside the CLASS statement block:
class sasuser.myclasses.one.class extends sashelp.fsp.object.class;
    /* define attribute */
    Public num sum
    / (description='sum attribute');

    _init: public Method
      / (State='O');
      _super();
      sum=0;
    endmethod;

    Sum: public method
      n:Num
      return=num;
        sum=sum+n;
        return(sum);
    endmethod;
endclass;
The approach above is appropriate for smaller projects where all class methods are maintained by a few developers. As projects increase in complexity and the number of developers involved grows, it is recommended that you use separate entries for class definitions and method implementations. It is the responsibility of each component developer to maintain an SCL entry that contains a USECLASS statement block for the method implementations.

USECLASS Statement

The USECLASS statement is similar to the CLASS statement, except that you cannot create class attributes or events in a USECLASS block. The ENDUSECLASS statement ends a USECLASS statement block.
In the following example, the methods are defined and stored in one SCL entry, whereas the method implementations are coded in a USECLASS statement block and are stored in a separate SCL entry (sasuser.myclasses.oneCode.scl). The following SCL code is stored in sasuser.myclasses.one.scl:
class sasuser.myclasses.one.class extends sashelp.fsp.object.class;
   _init: public method
     / (state='O',
        SCL='sasuser.myclasses.oneCode.scl');

   /* define attribute */
   Public num sum
   / (description='sum attribute');

   m1: method
       N:Num
       Return=Num
       /(SCL='sasuser.myclasses.oneCode.scl');
endclass;
The method implementations for the One class are stored in sasuser.myclasses.oneCode.scl:
useclass sasuser.myclasses.one.class;
   _init: public Method;
     _super();
     sum=0;
   endmethod;

   m1: method
       N:Num
       Return=Num;
       sum = sum + N;
       return(sum);
   endmethod;
enduseclass;
Note: The _super() routine is valid only inside CLASS or USECLASS blocks. The CALL SUPER routine can be used anywhere.