Creates a class using SCL code
| Category: |
Object Oriented
|
<ABSTRACT> CLASS
class-name<EXTENDS parent-class-name>
<SUPPORTED
supported-interface-clause>
<REQUIRED required-interface-clause>
< / (class-optional-clause)>
<(attribute-statements)>
<(method-declaration-statements)>
<(method-implementation-blocks)>
<(event-declaration-statements)>
<(eventhandler-declaration-statements)>
ENDCLASS;
|
-
ABSTRACT
-
is an optional keyword used to define a
class as an abstract class. Methods defined inside an abstract class are
not required to have method implementations. Abstract classes are used to
specify a common interface for several classes. An abstract class can not
be instantiated through the _NEW_ operator.
-
class-name
-
is the name of a class that you are creating,
which can be specified as a one- to four-level name.
-
parent-class-name
-
specifies the parent class of class-name and is specified as EXTENDS parent-class-name.
Parent-class-name can be specified
as a one- to four-level name.
If no EXTENDS clause is supplied, parent-class-name defaults to SASHELP.FSP.OBJECT.CLASS, which is the parent
class of all SAS/AF classes.
-
supported-interface-clause
-
lists the interfaces that this class supports.
Interfaces can be specified as follows:
SUPPORTED interface-1<,interface-2...>
The
interface names can
be specified as one- to four-level names. All of the methods listed in SUPPORTED
must be implemented in the CLASS block.
-
required-interface-clause
-
lists the interfaces required for this class.
Interfaces are specified as follows:
REQUIRED interface-1<,interface-2...>
The
interface names can
be specified as one- to four-level names. The REQUIRED interfaces are used
for the client-server model. For more information, see
INTERFACE.
-
class-optional-clause
-
specifies options for the class. Options
should be placed inside parentheses following a / (slash). Separate multiple
options with commas. Class options can be any of the
following:
-
Description=description
-
is a description of the CLASS
entry
-
MetaClass=class-name
-
is the four-level name of the CLASS entry
that contains the model of a class. The default MetaClass is SASHELP.FSP.CLASS.CLASS.
-
attribute-statements
-
defines the class attributes, which determine
how an object will look and behave. Attributes can either be scalars or arrays.
The syntax of a class attribute statement is: access-scope type var-name< / (attribute
options)>;
-
access-scope
-
can be one of the following:
-
`PUBLIC'
-
specifies that the attribute can be accessed
by any SCL program. DECLARE may be used in place of public scope.
-
`PRIVATE'
-
specifies that the attribute can be accessed
only from methods in the class where the attribute is defined.
-
`PROTECTED'
-
specifies that the attribute can be accessed
only from methods in subclasses of the class where the attribute is defined.
Since a class can be considered a subclass of itself, a protected attribute
can also be accessed from the class where it is defined.
-
type
-
is the data type of the attribute. NUM,
CHAR, LIST, OBJECT or a four-level class-name
are possible values of type.
-
var-name
-
is the name of the attribute. You can specify
a multi-dimensional array by providing an array dimension after var-name. For example:
PRIVATE num narray{3, 2, 3};
If an array variable has the same name as a method,
the method name has higher precedence when referencing that array. To avoid
ambiguity, use [ ] or { }
instead of ( ) to specify the array reference.
-
attribute-options
-
specifies options for a class attribute.
List options inside parentheses following a / (slash). Separate multiple
options with commas. Attribute-options can be
any of the following:
-
AutoCreate='N' | 'Y'
-
determines whether an SCL list is created
automatically when an instance of the class is created. If
AutoCreate='Y' (default), a four-level object name or SCL
list is created depending on the attribute type. If 'N',
then a four-level object name or SCL list is not created, and the user is
responsible for creating and deleting this list.
-
Category=category-name
-
specifies the category for an attribute.
Categories organize attributes so that you can display only attributes for
the category. You can create your own category names. Components that are
supplied with SAS software belong to the following categories:
Misc is the
default.
-
Description=attribute-description
-
specifies the description of the attribute.
When you click on an attribute in the Class Editor, this text is displayed
below the list of attributes.
-
Editable=`N' |
'Y'
-
determines whether attributes can be altered.
'Y' is the default.
If
EDITABLE='Y', then
the attribute can be set anywhere that it is in scope:
If EDITABLE='N', then
the ability to set the attribute is restricted based on its scope:
-
Editor=editor-entry-name
-
specifies a FRAME, SCL, or PROGRAM entry
that returns a value. The
Editor= option is
available for attributes of all types except OBJECT. If supplied, the specified
entry is displayed and executed by the Properties window when the ellipsis
button (...) in the cell is clicked. The value that is returned from the
entry is displayed in the cell in the Properties window.
Editors are typically FRAME entries that are designed
to aid an application developer in specifying a value for an attribute. For
example, for an attribute called 'textColor' that can be assigned to any hexcolor
string, you could design a FRAME entry window to help the user visually see
what the hexcolor string represents. The window could contain an RGB slider
control with a sample box that shows the color that is being created as a
user manipulates the red/green/blue sliders. In this example, you assign
the name of the FRAME entry as the value of EDITOR=,
and this window opens when a user selects the ...
button for the TEXTCOLOR attribute in the Properties window.
-
GetCAM=method-name
-
specifies the custom access method to be
executed when the value of the attribute is
queried.
-
InitialValue=initial-values
-
specifies an initial value for the attribute.
This option is valid only for attributes with types CHAR , NUM and SCL LIST.
For an example of using an SCL list as an initial value, see
Initializing the Values in a List.
-
Linkable=`N' |
'Y'
-
determines whether an attribute is linkable
from the Properties window. Only public attributes are linkable. Private
and protected attributes are not displayed in the Properties window.
Y is the
default.
-
SendEvent=`N' | 'Y'
-
determines whether an attribute sends an
event when modified. When
SENDEVENT='Y', SAS
assigns the Event Name, which has the format "attributeName Changed",
and registers it with the component. Y is the
default. When SENDEVENT='N', no Event name
will be registered
-
SetCAM=method-name
-
specifies the custom access method to be
executed when the attribute value is
assigned.
-
State='N'|'O'
-
determines whether the attribute is new
or is overridden.
N is the
default.
-
ValidValues=valid-values
-
specifies the values that are valid for
the CHARACTER attribute. Use a space or '/' or ',' to separate the values.
The following options are used for compatibility with
Version 6 classes:
-
Automatic=`Y' | 'N'
-
specifies whether var-name is an automatic instance
variable.
-
IV=V6-instance-variable-name
-
specifies the name of a Version 6 instance
variable.
-
PureIV=`Y' | 'N'
-
When
PureIV='Y',
it specifies that var-name is a pure Version
6 instance variable and that no associated Version 7 attribute will be created. N is the default.
-
method-declaration-statements
-
list the class methods.
For method-declaration-statements,
use the following syntax:
method-label-name : <access-scope> METHOD<parameter-list>
< / (method-options)>;
-
method-label-name
-
can be up to 32 characters and has the same
restrictions as an SCL label. By default, you should treat method-label-name the same as the method name. To define a
more descriptive method name which is over 32 characters, use the
method=
option.
-
access-scope
-
can be one of the following:
-
PUBLIC
-
designates a method that can be inherited
by subclasses and accessed anywhere the corresponding object exists. This
is the default.
-
PRIVATE
-
designates a method that can be accessed
only by methods in the class in which the method is defined. Private methods
will not be inherited by subclasses of the class.
-
PROTECTED
-
designates a method that can be accessed
only by subclasses in which the method is defined. Since a class can be considered
a subclass of itself, a protected method can also be accessed from the class
in which it is defined.
-
parameter-list
-
For parameter options such as using Input/Output/Update
to store the parameter storage, using "
:"
operator to specify the parameter type, using Optional=
to specify the varying arguments in the method, and using Return= to specify the method return type, as well as Arglist= and
Rest=, can all
be applied in the parameter list. For more information, see
METHOD.
-
method-options
-
specify options for a class method. You
must put the list inside parentheses that follow a / (slash). Separate multiple
options with commas. The available options
are
-
Description=method-description-string
-
specifies the description of the
method.
-
Enabled=`N'|'Y'
-
determines whether a method can be temporarily
disabled.
Y is the default.
-
Label='method-label'
-
identifies a method whose label is different
from the method-label-name. If the
Label= option
exists, the Method= option cannot be
used.
-
Method='method-name'
-
identifies the method-label-name as the label name and the 'method-name' will be used for the
method reference in the dot notation or CALL SEND routine. Since the 'method-name' is a string, you can extend the method name up
to 256 characters. If the
Method= option exists,
the Label= option cannot be used.
-
SCL |
Entry=four-level-entry-name-string
-
identifies the entry that contains the USECLASS
block that implements the method. This option is required when the method
is not implemented in the SCL entry that contains the CLASS statement
block.
-
Signature=`N'|'Y'
-
determines whether the method has a signature.
Y is the default. All methods in Version 6 classes have
Signature='N'. Adding parameter-list and removing
Signature='N' for each method will cause the SCL compiler
to generate signatures for that method. Signature='Y'
is required for method
overloading.
-
State=`O'|'N'
-
determines whether the method has been overridden
or is new.
-
Forward='N'|'Y'
-
determines whether the method can be forward
referenced when
Forward='Y'. The SCL compiler
is a one-pass compiler and will report errors when referencing a method that
has not been defined in the current class. Using Forward='Y' will allow the SCL compiler to suppress the error messages
and delay validation of the forward methods which are required to be defined
later in the current class. If the forward method is not defined before the
ENDCLASS statement, the SCL compiler will report the error. N is the default. This option can be used for methods calling
each other.
-
ArgDesc1 | ArgDesc2 |...| ArgDescN
=each-argument-description-string
-
specifies each argument description. This
option is used for documenting the parameters.
-
ReturnDesc=return-argument-description-string
-
specifies the return argument description.
This option is used for documenting the return
parameter.
-
method-implementation-blocks
-
contain any SCL statements for the defined
methods. These statements perform the operations of the method.
-
event-declaration-statements
-
define the class events. Declare the events
as follows:
EVENT event-string-name
< / (event-options)>;
-
event-string-name
-
is the name of the event you are declaring.
-
event-options
-
specifies options for the event. You must
put the list inside parentheses that follow a / (slash). Separate multiple
options with commas. Event options can be
-
Description=event-description
-
specifies the description of the
event.
-
Enabled=`N'|'Y'
-
determines whether an event can be temporarily
disabled.
Y is the default.
-
Method=string
-
identifies the method that handles the
event.
-
Send='Manual'|'After'|'Before'
-
determines when the object sends the event.
After is the
default.
-
eventhandler-declaration-statements
- define the event handler to be executed after the events
are triggered. The event handler is an SCL method that handles the event.
Declare the event handler as follows:
EVENTHANDLER eventhandler-name< / (eventhandler-options)>;
- eventhandler-name
- is the name of the event handler of an SCL class method
that you are declaring.
- eventhandler-options
- specifies options for the event handler. You must put the
list inside parentheses that follow a / (slash). Separate multiple options
with commas. Event handler options can be
Description=eventhandler-description
- specifies the description of the event
handler.
Enabled=`N'|'Y'
- determines whether an event handler can be temporarily disabled.
Y is the
default.
Event=event-name
- specifies the name of the event.
Method=string
- identifies the method that handles the event.
Sender='_SELF_'
| '_ALL_'
- identifies the location of the sender to trigger the event
handler. When
Sender='_SELF_', the event handler
will only listen to events from the class itself. When Sender='_ALL_', the event handler will listen to events from any other class.
Using the method _addEventHandler, you can dynamically add a sender to trigger
the event.
The CLASS statement enables you to use SCL to create
a class and to define attributes, methods, events and event handlers for the
class. The CLASS block is especially useful when you need to make many changes
to an existing class such as adding signatures to an existing class, or when
you want to create a class in batch mode. Using the CLASS block provides the
advantages of error detection at compile time and improved performance during
run time. It also enables you to use short-cut notation. Instead of using
_SELF_.attribute or _self.method(...) to reference the name of a class attribute or a class
method, you simply specify the attribute or method name. This makes programs
easier to read and maintain. In addition, you can overload method definitions,
which means that multiple methods can have the same name, but have different
numbers and types of parameters.
The program block that defines a class starts with a
CLASS statement and ends with an ENDCLASS statement. A CLASS block can contain
statements that define attributes, methods, events, event handlers and even
METHOD statement blocks implementing the operations for methods. You can
also put the METHOD statements that implement class methods in another SCL
entry when you use the SCL= method option to specify the name of that entry.
Then, in the SCL entry that is specified with SCL=, define the methods for
the class within a USECLASS statement block. Defining methods in a separate
entry is useful for enabling class methods to be created, tested, or maintained
by multiple application developers. For more information, see METHOD.
To create a
class from an SCL entry that contains a
CLASS block, you must compile and save the SCL entry as a CLASS entry. To
do this, either issue the SAVECLASS command or select
| File |
![[arrow]](../common/images/arrow.gif) |
Save Class |
from the SCL Source
Editor. This is equivalent to using the Class Editor to interactively create
a CLASS entry. However, the Class Editor provides a graphical view of the
class, whereas the CLASS statement in SCL provides a language view of the
class.
In methods that are defined in a CLASS statement block,
all references to the methods and the attributes of the class can bypass two-level
references to _SELF_.attribute and _SELF_.method(...). Because these methods are defined within the class,
the SCL compiler can detect whether an undefined variable is a local variable
or a class attribute.
You can also use the _super method in method code inside
a CLASS statement block without having to specify either an object identifier
or the method whose super method you are calling. You can use the _super method
to call any method. For example, to invoke the super ADD method, you would
use
_super.add();
To override the _init method, you must first call the
super _init method before overriding the _init method. For example:
_super._init();
...statements that define the
overridden _init method ...
Any SCL function or routine can be called inside a METHOD
statement block that is inside a CLASS block. Outside the METHOD statement
block, only class attribute statements, event statements and event handlers
are allowed in a CLASS block. Other than the IMPORT statement, no SCL statements
can be written outside the CLASS block.
METHOD blocks can include labeled sections. However,
labeled sections that are outside a method block must be re-coded as PRIVATE
methods, and the LINK statements that call them must be changed to method
calls. This programming style will make your applications more consistent
with the object-oriented paradigm.
If a local variable that is defined in a METHOD block
has the same name as a class attribute, SCL gives precedence to the local
variable. If a class method has the same name as any SCL-supported function,
SCL gives precedence to the function. If an attribute array has the same name
as a class method, SCL gives precedence to the method. It is probably best
to avoid using the same name for multiple local variables, class attributes,
method names or arrays to avoid problems.
The CLASS statement also enables you to define method
definitions for overloading methods, which means that multiple methods have
the same name. Methods that have the same names are allowed in a CLASS block
only if the signatures, or parameter numbers or types, are different. For
example, a class can have one COMBINE method that has numeric parameters and
adds parameter values, and another COMBINE method that has character parameters
and concatenates parameter values.
Inheritance from multiple classes is not supported in
class syntax, but is allowed with interface syntax. For more information,
see INTERFACE.
This example defines the Arith class, a subclass of
Sashelp.Fsp.Object.class, and implements the methods in the CLASS entry. The
example shows the METHOD statements using the RETURN= option and then RETURN
statements returning values to the caller.
class work.classes.arith.class;
public num total;
public char catstr;
/* A method that adds numeric values */
add: public method n1:num n2:num return=num;
total = n1 + n2;
return (total);
endmethod;
/* A method that concatenates */
/* character values */
concat: public method c1:char c2:char return=char;
catstr = c1 || c2;
return (catstr);
endmethod;
endclass;
This example defines the Combine class and specifies
the SCL entry in which the methods are implemented. The class uses overloaded
COMBINE methods, one to process numeric values and another to process character
values. The code that implements the methods is defined in a USECLASS block.
class work.classes.combine.class;
public num total;
public char catstr;
combine: public method n1:num n2:num return=num
/ (scl='work.classes.combine.scl');
combine: public method c1:char c2:char
return=char
/ (scl='work.classes.combine.scl');
endclass;
Here is the USECLASS block that contains the method
implementations for WORK.CLASSES.COMBINE.CLASS:
useclass work.classes.combine.class;
combine: public method
n1:num n2:num return=num;
total = n1 + n2;
return (total);
endmethod;
combine: public method
c1:char c2:char return=char;
catstr = c1 || c2;
return (catstr);
endmethod;
enduseclass;
This example imports the Collection class, which is
provided with SAS/AF software, and shows several forms of attribute declarations,
method declarations, and overloading methods. Attributes list1 and list2,
which define SCL list initialization, can also be found in this example.
import sashelp.fsp.collection.class;
class work.classes.myclass.class
extends sashelp.fsp.object.class
/ (description = 'my first class file');
/* simple attribute with no options */
public num num1;
/* Attribute with options */
public num num2
/ (description = 'second numeric attribute',
initialvalue= 3,
validvalues = '1 2 3');
/* Another attribute with options */
public char string1
/ (editable = 'n', linkable = 'n',
initialvalue = 'abc');
/* SCL List initializations:items without name*/
public list list1
/ (InitialValue={1, 2, 3, 'abc', 'def', 4, 5, 6}
);
/* SCL List initializations:Items with name.*/
/* Address is a sublist of list2 */
public list list2
/ (InitialValue={name='John Doe', Number=100,
Address={State='NC', CITY='CARY'},
Office='Bldg Z'} )
/* Private array attribute */
private num arr(3) ;
/* Private list attribute */
private list list;
/* Protected collection attribute */
protected collection coll;
/* public method m0 */
m0: Public method
/* External method implementations */
/ (scl='mylib.classes.b.scl',
label = 'M0',
description='test method m0');
/* Public method m1 */
/* with no method options */
m1: public method ;
...more SAS statements...
endmethod;
/* Private overloading method m1 */
/* with numeric parameter */
m1: private method n: num;
...more SAS statements...
endmethod;
/* Protected overloaded method m1.
* Method implementations should be placed in
* work.classes.c.scl */
m1: protected method s: char
/* external method implementation */
/ (scl = 'work.classes.c.scl');
/* Other public method */
m2: method return=num;
...more SAS statements...
return (1);
endmethod;
/* Private method */
m3: private method;
...more SAS statements...
endmethod;
endclass;
This example shows how to use the _super method as well
as short-cut references to _SELF_:
CLASS work.classes.another.class;
Public Num n1;
Public Num n2;
Public Char c1;
Public Char c2;
Public Num m(3);
_Init: method / (State='O');
DCL Num n2;
DCL Char c2;
/* Equivalent to call super(_init); */
_SUPER();
/* Equivalent to _SELF_.N1 = 1 */
n1 = 1;
/* Local variable N2 dominates class */
/* attribute N2 */
n2 = 1;
m{1} = abs(n2);
/* Uses { to avoid ambiguity */
/* Equivalent to _SELF_.C1 = 'a' */
c1 = 'a';
/* Local variable C2 dominates */
/* class attribute C2 */
c2 = 'a';
endmethod;
/* commonly used method can be PRIVATE */
Common: Private Method a:Num;
...more SCL statements...
a = a + 1;
endmethod;
M: method;
/* Equivalent to */
/* if _SELF_.N1 > 0 then */
if n1 > 0 then
/* Equivalent to */
/* _SELF_.N1 + 1; */
n1 + 1;
common(n1);
endmethod;
/* Method M1 with numeric parameter */
M: method n: Num;
/* Equivalent to _SELF_.M(); */
M();
common(n1);
endmethod;
endclass;
This example shows a setCAM method, M1, which will be
invoked when the attribute N is modified in the _init method.
Class work.mycat.camDemo.class;
Public num n / (initialValue = 5,
setCam='m1');
_init: Method / (State='O');
_super();
n = 3;
EndMethod;
m1: Method nParm:Num;
/* - nParm is input value of attribute n */
nParm = nParm + 100;
/* nParm is output value of attribute n */
EndMethod;
EndClass;
To reference the camDemo class, you can code the following
program:
Init:
DCL camDemo obj = _new_ camDemo();
obj.n = 7;
/* Using the SCL debugger to trace the sequence
* of this program, you will find the value
* of obj.n = 107 */
put obj.n=;
Return;
This example shows a system-defined event, 'n Changed',
which will be automatically generated to associate with the attribute N.
An event handler, M1, which is associated with the 'n Changed' event is also
written and will be executed when the attribute N is modified. Another user-defined
event, 'myEvent', is created by the EVENT statement. The associated event
handler, M2, will be executed when an explicit _sendEvent method is executed.
Class work.mycat.eDemo.class;
Public num n; /* sendEvent='Y' is default*/
Public char c / (sendEvent='N');
Event 'myEvent'
/ (method='m2');
EventHandler m1
/ (Sender='_SELF_',
Event='n Changed');
EventHandler m2
/ (Sender='_ALL_',
Event='myEvent');
m1: method a:list;
Put 'Event is triggered by attribute N';
endMethod;
m2: method a:string b:num ;
Put 'Event is triggered by _sendEvent';
return (100);
endMethod;
EndClass;
You could use the following program to trace the control
sequence of the event handler by using the SCL debugger.
init:
DCL eDemo obj = _new_ eDemo();
obj.n = 3; /* will trigger the m1 */
obj._sendEvent('myEvent','abc',3);
Return;
This example shows how to use the method option Forward='Y'
to write a method, M1, which can invoke another method, M2, defined after
the current method, M1. Without the Forward='Y' option, the SCL compiler will
issue an error. The M1 method contains Optional=, which actually includes
two overloading methods.
Class mylib.mycat.forward.class;
m2: Method n:num c:char Return=Num / (Forward='Y');
m1: Method n1:num Optional=n2:num Arglist=argList
Return=Num;
DCL Num listLen = listlen(argList);
DCL Num retVal;
if (listLen = 1) then
retVal = m2(n1, 'abc');
else if (listLen = 2) then
retVal = m2(n2, 'abc');
Return(retVal);
EndMEthod;
m2: Method n:num c:char Return=Num;
Return(n+length(c));
EndMethod;
EndClass;
ARRAY
CREATESCL
ENDCLASS
METHOD
USECLASS
Copyright © 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.