Chapter Contents |
Previous |
Next |
CLASS |
Category: | Object Oriented |
Syntax |
<ABSTRACT> CLASS
class-name<EXTENDS parent-class-name> <SUPPORTS supports-interface-clause> <REQUIRES requires-interface-clause> < / (class-optional-clause)> <(attribute-statements)> <(method-declaration-statements)> <(method-implementation-blocks)> <(event-declaration-statements)> <(eventhandler-declaration-statements)> ENDCLASS; |
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.
SUPPORTSinterface-1<,interface-2...>
The interface names can be specified as one- to four-level names. All of the methods listed in SUPPORTS must be implemented in the CLASS block.
REQUIRES interface-1<,interface-2...>
The interface names can be specified as one- to four-level names. The REQUIRES interfaces are used for the client-server model. For more information, see INTERFACE.
Description
=descriptionMetaClass
=class-name
`PUBLIC'
`PRIVATE'
`PROTECTED'
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.
AutoCreate
='N'
| 'Y'
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-nameAppearance | |
Data | |
Drag and drop | |
Help | |
Misc (Miscellaneous) | |
Region | |
Size/location |
Description
=attribute-descriptionEditable
=`N'
|
'Y'
'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-nameEditor
= 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-nameInitialValue
=initial-valuesLinkable
=`N'
| 'Y'
Y
is the
default.SendEvent
=`N'
| 'Y'
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 registeredSetCAM
=method-nameState
='N'
|'O'
N
is the
default.ValidValues
=valid-valuesThe following options are used for compatibility with Version 6 classes:
Automatic
=`Y'
| 'N'
IV
=V6-instance-variable-namePureIV
=`Y'
| 'N'
PureIV='Y'
,
it specifies that var-name is a pure Version
6 instance variable and that no associated Version 8 attribute will be created. N
is the default.For method-declaration-statements, use the following syntax:
method-label-name : <access-scope> METHOD<parameter-list>
< / (method-options)>;
method=
option.
PUBLIC
PRIVATE
PROTECTED
:
"
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.
Abstract
='N'
| 'Y'
'N'
.Description
=method-description-stringEnabled
=`N'
|'Y'
Y
is the default.Label
='method-label'Label=
option
exists, the Method=
option cannot be
used.Method
='method-name'Method=
option exists,
the Label=
option cannot be
used.Native
='/executable-name:nNote: This option is generated by the CREATESCL
function.
SCL | Entry
=four-level-entry-name-stringSignature
=`N'
|'Y'
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'
Forward
='N'
|'Y'
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 ReturnDesc
=return-argument-description-string
EVENT event-string-name < / (event-options)>;
Description
=event-descriptionEnabled
=`N'
|'Y'
Y
is the default.Method
=stringSend
='Manual'
|'After'
|'Before'
After is the default.
EVENTHANDLER eventhandler-name< / (eventhandler-options)>;
Description
=eventhandler-descriptionEnabled
=`N'
|'Y'
Y
is the
default.Event
=event-nameMethod
=stringSender
='_SELF_'
| '_ALL_'
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.Details |
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 | Save Class |
Do not declare the _SELF_, _FRAME_, _CFRAME_, _METHOD_, or _EVENT_ system variables inside a CLASS or USECLASS block. SCL automatically sets these values when it is running methods that are defined in CLASS or USECLASS blocks. Redefining any of these system variables can introduce unexpected behavior.
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.
Examples |
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;
See Also |
Chapter Contents |
Previous |
Next |
Top of Page |
Copyright 1999 by SAS Institute Inc., Cary, NC, USA. All rights reserved.