Using SCL to Instantiate Classes

Introduction

You can instantiate a SAS/AF class with the _NEW_ operator, which combines the actions of the LOADCLASS function with the initialization of the object with its _new method. For example:
dcl sashelp.classes.librarylist_c.class libraries;
init:
  libraries = _new_ sashelp.classes.librarylist_c();
  call putlist(libraries.items, 'Libraries=', 1);
return;
You can use the _NEW_ operator with the IMPORT statement so that you can refer to a class without having to specify its entire four-level catalog name. The IMPORT statement specifies a search path for CLASS entry references in an SCL program. You can also combine the _NEW_ operator with the DECLARE (or DCL) statement for single-step declaration and instantiation:
import sashelp.classes.librarylist_c.class;
dcl librarylist_c document=_new_ librarylist_c();

Using Constructors

Introduction

The _NEW_ operator also enables you to create an instance of a class and to run a class constructor. A constructor is a method that is automatically invoked whenever an object is instantiated. You can use a constructor to initialize the object to a valid starting state. The method that is used as the constructor of a class has the same name as the class. You can specify a signature with no arguments to override the default constructor (that is, its signature is ()V), or you can overload the constructor with signatures that use one or more arguments. You cannot, however, specify a return type.
Consider a class that is defined as follows:
class sasuser.test.Account
   extends sashelp.fsp.object.class;
   /* attributes */
   public num accountNumber;
   public num balance;

   /* constructor */
   Account: public method
      id:input:num;
      accountNumber=id;
      balance=0;
   endmethod;
endclass;
When an Account object is instantiated, the constructor assigns a specific number as the accountNumber and initializes the balance attribute to 0. For example:
import sasuser.test.Account.class;
dcl account newAccount = _new_ account(1234);
The _NEW_ operator calls the account constructor method and passes a value 1234 to its numeric argument. This creates a new Account object that has 1234 as its accountNumber and a balance of 0.
You can also overload the constructor to accept a different number of arguments. Consider a subclass of the Data Set List Model class:
class sasuser.myclasses.ourData
   extends sashelp.classes.datasetlist_c.class;

   OurData: public method
      lib:char;
      /* library is an inherited attribute */
      if lib ne ''
         then library=lib;  /* set library attribute */
   endmethod;

   OurData: public method
      lib:char
      level:num;
      /* library and levelCount are inherited attributes */
      if lib ne ''
         then library=lib;  /* set library attribute */
      if level in (1,2)
         then levelCount=level;  /* set levelCount attribute */
   endmethod;
endclass;
You can pass one argument to the _NEW_ operator to call the constructor with one argument in its signature. In the following example, the constructor initializes the library attribute:
import sasuser.test.OurData.class;
dcl OurData table = _new_ OurData('sasuser');
You could also pass two arguments to the _NEW_ operator to call the constructor with two arguments in its signature. In the following example, the constructor sets the library and typeFilter attributes:
import sasuser.test.OurData.class;
dcl OurData table = _new_ OurData('sasuser',1); 
Because the library attribute of the table object is initialized in both cases, you can immediately query table.items to retrieve the list of SAS tables in the specified library. If typeFilter is 1, then the items list contains only the names of the tables and not the full two-level SAS name.
For complete information on the _NEW_ operator and constructors, see the SAS Component Language: Reference.

Defining Constructors in the SCL for a Class

The Account class and OurData class examples above demonstrate how you can define and implement constructors for a class within a CLASS/ENDCLASS block. There are several important items to remember when you define constructors in the SCL for a class:
  • If you specify the Label metadata item in the method definition for the constructor, it must be the same as the name of the class.
  • To override the default constructor for a class, add the STATE='O' metadata item to the method definition. For example, you could override the default constructor for a class named Document with the following code:
    Document: public method
       /(State='O',
         Description='Override of the default constructor',
         SCL='sasuser.myclasses.Document.scl');
    Note that the default constructor has a signature of ()V.
  • If you want to use a method with the same name as the class and not have it function as a constructor, you must specify a CONSTRUCTOR='N' metadata item in the method definition. For example:
    class sasuser.myclasses.Report
       extends sashelp.fsp.Object.class;
       /* constructor override with sigstring ()V */
       Report: public method
          /(State='O',
            Description='Constructor method',
            SCL='sasuser.myclasses.Report.scl');
    
       /* method with sigstring (C)V */
       Report: public method
          ch:char
          /(State='N',      /* optional */
            Description='Report method',
            SCL='sasuser.myclasses.OtherMethods.scl',
            Constructor='N');
    endclass;
  • By default, all constructors are stored in the CLASS entry as methods named _initConstructor. If the method definition specifies CONSTRUCTOR='N', then the method is stored with the same name as the class. If you add constructors to a class that you define in SCL and save the SCL as a CLASS entry, the constructors appear in the Methods list of the Class Editor with the same name as the class. For example, if you opened the Report class defined above in the Class Editor, you would see two methods: an overridden method named Report and a new method named Report.

Defining Constructors Using the Class Editor

You can also use the Class Editor to override the default constructor or to add new constructors to a class, using the same processes that you would for any other method. However, there are several other items you must remember when working with constructors in the Class Editor:
  • You can override the default constructor for a class that you are editing in the Class Editor by selecting the method with the same name as the class, then selecting Override from the pop-up menu.
  • You can overload the class constructor by adding a new method with the same name and providing a signature other than ()V.
  • When you edit the class constructor in the Class Editor, the value of the SCL Label field defaults to the name of the class. You cannot edit this value.
  • Unlike defining a constructor in SCL, if you add a method with the same name as the class in the Class Editor, it is not stored on the class as a constructor, but rather as a standard method.
  • If you save the class as an SCL entry from the Class Editor and view the SCL class definition code that is generated, the constructors appear as methods with the same name as the class. For example, if you edit a class named Document, override its Document method in the Class Editor, and save it as an SCL entry, the SCL entry includes the following code:
    class sasuser.myclasses.Document
       extends sashelp.fsp.Object.class;
    
    Document: public method
        /(State='O',
          Description='Override of the default constructor',
          SCL='sasuser.myclasses.Document.scl');
    
    /* ...insert additional methods here... */
    endclass;