[r9260]: docs / branches / 4.1 / trunk / rexxref / provide.xml Maximize Restore History

Download this file

provide.xml    990 lines (915 with data), 44.0 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
<!--#########################################################################
#
# Description: Open Object Rexx: Reference SGML file.
#
# Copyright (c) 2005-2009, Rexx Language Association. All rights reserved.
# Portions Copyright (c) 2004, IBM Corporation. All rights reserved.
#
# This program and the accompanying materials are made available under
# the terms of the Common Public License v1.0 which accompanies this
# distribution. A copy is also available at the following address:
# http://www.oorexx.org/license.html
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the distribution.
#
# Neither the name of Rexx Language Association nor the names
# of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Author(s):
# W. David Ashley <dashley@us.ibm.com>
#
#########################################################################
-->
<chapter id="provide"><title>Objects and Classes</title>
<indexterm><primary>object method</primary></indexterm>
<para>This chapter provides an overview of the Rexx class structure.</para>
<para>A Rexx object consists of object methods
<indexterm><primary>class methods</primary></indexterm>
and object variables ("attributes"). Sending
a message to an object causes the object to perform some action; a method
whose name matches the message name defines the action that is performed.
Only an object's methods can access the object variables belonging to
an object. EXPOSE instructions within an object's methods specify which object
variables the methods will use. Any variables not exposed are local to the method and
are dropped on return from a method.</para>
<para>You can create
an object by sending a message to a class object&mdash;typically a "new" method. An object created from a
class is an <emphasis>instance</emphasis> of that class.
The methods a class defines
for its instances are called the <emphasis>instance methods</emphasis>
<indexterm><primary>instance methods</primary></indexterm>
of that class. These are the object methods that are available for every instance of the class. Classes can also
define <emphasis>class methods</emphasis>, which are a class's own
object methods.</para>
<note><title>Note</title>
<para>When referring to instance methods (for objects
other than classes) or class methods (for classes), this book uses the
term <emphasis>methods</emphasis> when the meaning is clear from the context.
When referring to instance methods and class methods of classes, this book uses
the qualified terms to avoid possible confusion.</para></note>
<section id="typcla"><title>Types of Classes</title>
<para>There are four kinds of classes: </para>
<itemizedlist>
<listitem><para>Object classes</para></listitem>
<listitem><para>Mixin classes</para></listitem>
<listitem><para>Abstract classes</para></listitem>
<listitem><para>Metaclasses</para></listitem></itemizedlist>
<para> The following sections explain these.</para>
<section id="objcla"><title>Object Classes</title>
<indexterm><primary>object classes</primary></indexterm>
<indexterm><primary>class</primary>
<secondary>types</secondary>
<tertiary>object</tertiary></indexterm>
<para>An <emphasis>object class</emphasis> is a factory
for producing objects. An object class creates objects (instances) and provides
methods that these objects can use. An object acquires the instance methods
of the class to which it belongs at the time of its creation. If a class gains
additional methods, objects created before the definition of these methods
do not acquire the new or changed methods.</para>
<para>The instance variables within an object are created on demand whenever a method
EXPOSEs an object variable. The class creates the object instance, defines the methods
the object has, and the object instance completes the job of constructing the object.
</para>
<para>
The <link linkend="clsString">String class</link> and the
<link linkend="clsArray">Array Class</link>
are examples of object classes.</para>
</section>
<section id="xmixin"><title>Mixin Classes</title>
<indexterm><primary>mixin classes</primary></indexterm>
<indexterm><primary>class</primary>
<secondary>types</secondary>
<tertiary>mixin</tertiary></indexterm>
<para>Classes can inherit from more than the single superclass from
which they were created. This is called
<emphasis>multiple inheritance</emphasis>. Classes designed
to add a set of instance and class
methods to other classes are called <emphasis>mixin classes</emphasis>,
or simply mixins.</para>
<para>You can add mixin methods to an existing class by sending an INHERIT
message or using the INHERIT option on the <link linkend="clasdi">::CLASS directive</link>.
In either case, the class to be inherited must be a mixin. During both class
creation and multiple inheritance, subclasses inherit both class and instance
methods from their superclasses.</para>
<para>Mixins are always associated
<indexterm><primary>base class for mixins</primary></indexterm>
with a <emphasis>base class</emphasis>, which is the mixin's first non-mixin
superclass. Any subclass of the mixin's base class can (directly or indirectly)
inherit a mixin; other classes cannot. For example, a mixin class created
as a subclass of the Array class can only be inherited by other Array subclasses.
Mixins that use the Object class as a base class can be inherited by any class.
</para>
<para>To create a new mixin class, you send a MIXINCLASS message to an existing
class or use the ::CLASS directive with the MIXINCLASS option. A mixin class
is also an object class and can create instances of the class.</para>
</section>
<section id="abscla"><title>Abstract Classes</title>
<indexterm><primary>abstract class, definition</primary></indexterm>
<indexterm><primary>class</primary>
<secondary>types</secondary>
<tertiary>abstract</tertiary></indexterm>
<para><emphasis>Abstract classes</emphasis> provide definitions for instance
methods and class methods
but are not intended to create instances. Abstract classes often define the
message interfaces that subclasses should implement.</para>
<para>You create an abstract class like object or mixin classes. No extra
messages or keywords on the ::CLASS directive are necessary. Rexx does not
prevent users from creating instances of abstract classes.
It is possible to create abstract methods on a class. An abstract method is a
placeholder that subclasses are expected to override. Failing to provide a real
method implementation will result in an error when the abstract version is called.
</para>
</section>
<section id="xmetac"><title>Metaclasses</title>
<indexterm><primary>metaclasses</primary></indexterm>
<indexterm><primary>class</primary>
<secondary>types</secondary>
<tertiary>metaclass</tertiary></indexterm>
<para>A <emphasis>metaclass</emphasis> is a class you
can use to create another class. The only metaclass that Rexx provides is
.Class, the Class class. The Class class is the metaclass of all the classes
Rexx provides. This means that instances of .Class are themselves classes.
The Class class is like a factory for producing the factories that produce
objects.</para>
<para>To change the behavior of an object that is an instance, you generally
use subclassing. For example, you can create Statarray, a subclass of the
<link linkend="clsArray">Array class</link>.
The statArray class can include a
method for computing a total of all the numeric elements of an array.</para>
<programlisting>
/* Creating an array subclass for statistics */
::class statArray subclass array public
::method init /* Initialize running total and forward to superclass */
expose total
total = 0
/* <link linkend="mthMessageNew">init</link> describes the init method. */
forward class (super)
::method put /* Modify to increment running total */
expose total
use arg value
total = total + value /* Should verify that value is numeric!!! */
forward class (super)
::method "[]=" /* Modify to increment running total */
forward message "PUT"
::method remove /* Modify to decrement running total */
expose total
use arg index
forward message "AT" continue
total = total - result
forward class (super)
::method average /* Return the average of the array elements */
expose total
return total / self~items
::method total /* Return the running total of the array elements */
expose total
return total
</programlisting>
<para>You can use this method on the individual array
<emphasis>instances</emphasis>, so it is an
<emphasis>instance method</emphasis>.</para>
<para>However, if you want to change the behavior of the factory producing the
arrays, you need a new class method. One way to do
this is to use the ::METHOD directive with the CLASS option. Another way to
add a <emphasis>class</emphasis> method is to create a new metaclass that
changes the behavior
of the Statarray class. A new metaclass is a subclass of .class.</para>
<para>You can use a metaclass by specifying it in a SUBCLASS or MIXINCLASS
message or on a ::CLASS directive with the METACLASS option.</para>
<para>If you are adding a highly specialized class method useful only for a
particular class, use the ::METHOD directive with the CLASS option. However,
if you are adding a class method that would be useful for many classes, such
as an instance counter that counts how many instances a class creates,
you use a metaclass.</para>
<para>The following examples add a class method that keeps a running total of
instances created. The first version uses the ::METHOD directive with the
CLASS option. The second version uses a metaclass.</para>
<para><emphasis role="bold">Version 1</emphasis></para>
<indexterm><primary>examples</primary>
<secondary>metaclass</secondary></indexterm>
<programlisting>
/* Adding a class method using ::METHOD */
a = .point~new(1,1) /* Create some point instances */
say "Created point instance" a
b = .point~new(2,2) /* create another point instance */
say "Created point instance" b
c = .point~new(3,3) /* create another point instance */
say "Created point instance" c
/* ask the point class how many */
/* instances it has created */
say "The point class has created" .point~instances "instances."
::class point public /* create Point class */
::method init class
expose instanceCount
instanceCount = 0 /* Initialize instanceCount */
forward class (super) /* Forward INIT to superclass */
::method new class
expose instanceCount /* Creating a new instance */
instanceCount = instanceCount + 1 /* Bump the count */
forward class (super) /* Forward NEW to superclass */
::method instances class
expose instanceCount /* Return the instance count */
return instanceCount
::method init
expose xVal yVal /* Set object variables */
use arg xVal, yVal /* as passed on NEW */
::method string
expose xVal yVal /* Use object variables */
return "("xVal","yVal")" /* to return string value */
</programlisting>
<para><emphasis role="bold">Version 2</emphasis></para>
<programlisting>
/* Adding a class method using a metaclass */
a = .point~new(1,1) /* Create some point instances */
say "Created point instance" a
b = .point~new(2,2)
say "Created point instance" b
c = .point~new(3,3)
say "Created point instance" c
/* ask the point class how many */
/* instances it has created */
say "The point class has created" .point~instances "instances."
::class InstanceCounter subclass class /* Create a new metaclass that */
/* will count its instances */
::method init
expose instanceCount
instanceCount = 0 /* Initialize instanceCount */
forward class (super) /* Forward INIT to superclass */
::method new
expose instanceCount /* Creating a new instance */
instanceCount = instanceCount + 1 /* Bump the count */
forward class (super) /* Forward NEW to superclass */
::method instances
expose instanceCount /* Return the instance count */
return instanceCount
::class point public metaclass InstanceCounter /* Create Point class */
/* using InstanceCounter metaclass */
::method init
expose xVal yVal /* Set object variables */
use arg xVal, yVal /* as passed on NEW */
::method string
expose xVal yVal /* Use object variables */
return "("xVal","yVal")" /* to return string value */
</programlisting>
</section>
</section>
<section id="xcremet"><title>Creating and Using Classes and Methods</title>
<para>You can define a class using either directives or messages.</para>
<para>To define a class using directives, you place a ::CLASS directive after the
main part of your source program:</para>
<programlisting>
::class "Account"
</programlisting>
<para>This creates an Account class that is a subclass of the Object class. Object
is the default superclass if one is not specified.
(See <link linkend="clsObject">The Object Class</link> for a description of the
Object class.) The string &quot;Account&quot;
is a string identifier for the new class. The string identifier is both the internal
class name and the name of the <link linkend="ensym">environment symbol</link> used to locate your new class instance.
</para>
<para>Now you can use <link linkend="methd">::METHOD directives</link> to add methods to your new class. The
::METHOD directives must immediately follow the ::CLASS directive that creates
the class. </para>
<programlisting>
::method type
return "an account"
::method "name="
expose name
use arg name
::method name
expose name
return name
</programlisting>
<para>This adds the methods TYPE, NAME, and NAME= to the Account class.</para>
<para>You can create a subclass of the Account class and define a method for
it: </para>
<programlisting>
::class "Savings" subclass account
::method type
return "a savings account"
</programlisting>
<para>Now you can create an instance of the Savings class with the NEW method
(see <link linkend="mthClassNew">NEW</link>) and send TYPE, NAME, and NAME= messages
to that instance:</para>
<programlisting>
asav = .savings~new
say asav~type
asav~name = "John Smith"
</programlisting>
<para>The Account class methods NAME and NAME= create a pair of access methods
to the account object variable NAME. The following directive sequence creates
the NAME and NAME= methods: </para>
<programlisting>
::method "name="
expose name
use arg name
::method name
expose name
return name
</programlisting>
<para>You can replace this with a single <link linkend="attrd">::ATTRIBUTE directive</link>.
For example, the directive </para>
<programlisting>
::attribute name
</programlisting>
<para>adds two methods, NAME and NAME= to a class. These methods perform the
same function as the NAME and NAME= methods in the original example. The NAME
method returns the current value of the object variable NAME; the NAME= method
assigns a new value to the object variable NAME.</para>
<para>In addition to defining operational methods and attribute methods, you can add
"constant" methods to a class using the <link linkend="constantd">::CONSTANT directive</link>.
The ::CONSTANT directive will create both a class method and an instance method to the class
definition. The constant method will always return the same constant value, and can be
invoked by sending a message to either the class or an instance method. For example, you
might add the following constant to your Account class:</para>
<programlisting>
::constant checkingMinimum 200
</programlisting>
<para>This value can be retrieved using either of the following methods</para>
<programlisting>
say .Account~checkingMinimum -- displays "200"
asave = .savings~new
say asave~checkingMinimum -- also displays "200"
</programlisting>
<section id="usingcl"><title>Using Classes</title>
<para>When you create a new class, it is always a subclass of an existing class.
You can create new classes with the ::CLASS directive or by sending the SUBCLASS
or MIXINCLASS message to an existing class. If you specify neither the SUBCLASS
nor the MIXINCLASS option on the ::CLASS directive, the superclass for the
new class is the Object class, and it is not a mixin class.</para>
<para>Example of creating a new class using a message: </para>
<programlisting>
persistence = .object~mixinclass("Persistence")
myarray=.array~subclass("myarray")~~inherit(persistence)
</programlisting>
<para>Example of creating a new class using the directive:</para>
<programlisting>
::class persistence mixinclass object
::class myarray subclass array inherit persistence
</programlisting>
</section>
<section id="xscope"><title>Scope</title>
<indexterm><primary>method</primary>
<secondary>scope</secondary></indexterm>
<indexterm><primary>scope</primary>
<secondary>description</secondary></indexterm>
<para>A <emphasis>scope</emphasis> refers to the methods
and object variables defined for a single class (not including the superclasses).
Only methods defined in a
particular scope can access the object variables within that scope. This means
that object variables in a subclass can have the same names as object variables
used by a superclass, because the variables are created at different scopes.</para>
</section>
<section id="usesem">
<title>Defining Instance Methods with SETMETHOD or ENHANCED</title>
<para>In Rexx, methods are usually associated with instances using classes, but
it is also possible to add methods directly to an instance using the SETMETHOD
(see <link linkend="mthObjectSetMethod">SETMETHOD</link>) or ENHANCED (see
<link linkend="mthClassEnhanced">ENHANCED</link>) method.</para>
<para>All subclasses of the Object class inherit SETMETHOD. You can use
SETMETHOD to create one-off objects, objects that must be absolutely
unique so that a class that is capable of creating other instances is not
necessary. The Class class also provides an ENHANCED method that lets you
create new instances of a class with additional methods. The methods and the
object variables defined on an object with SETMETHOD or ENHANCED form a separate
scope, like the scopes the class hierarchy defines.</para>
</section>
<section id="methna"><title>Method Names</title>
<para>A method
name can be any string. When an object receives a message, the language processor
searches for a method whose name matches the message name in uppercase.</para>
<note><title>Note</title>
<para>The language processor also translates the specified name of all
methods added to objects into uppercase characters.</para></note>
<para>You must surround a method name with quotation marks when it contains
characters that are not allowed in a symbol (for example, the operator
characters). The following example creates a new class (the Cost class),
defines a new method (%), creates an instance of the Cost class (mycost),
and sends a <computeroutput>%</computeroutput> message
to <computeroutput>mycost</computeroutput>: </para>
<programlisting>
cost=.object~subclass("A cost")
cost~define("%", &apos;expose p; say "Enter a price."; pull p; say p*1.07;&apos;)
mycost=cost~new
mycost~"%" /* Produces: Enter a price. */
/* If the user specifies a price of 100, */
/* produces: 107.00 */
</programlisting>
</section>
<section id="xmeths"><title>Default Search Order for Method Selection</title>
<indexterm><primary>method</primary>
<secondary>search order</secondary>
<tertiary>changing</tertiary></indexterm>
<indexterm><primary>method</primary>
<secondary>selection</secondary>
<tertiary>search order</tertiary></indexterm>
<indexterm><primary>default</primary>
<secondary>search order for methods</secondary></indexterm>
<indexterm><primary>search order</primary>
<secondary>for methods</secondary>
<tertiary>default</tertiary></indexterm>
<para>The search order for a method name matching the message is for: </para>
<orderedlist>
<listitem><para>A method the object itself defines with SETMETHOD or ENHANCED.
(See <link linkend="mthObjectSetMethod">SETMETHOD</link> .)</para></listitem>
<listitem><para>A method the object's class defines. (Note that an object
acquires the instance methods of the class to which it belongs at the time of
its creation. If a class gains additional methods, objects created before the
definition of these methods do not acquire these methods.)</para></listitem>
<listitem><para>A method that a superclass of the object's class defines.
This is also limited to methods that were available when the object was
created. The order of the INHERIT (see
<link linkend="mthClassInherit">INHERIT</link>) messages sent to an object's
class determines the search order of the superclass method definitions.
</para></listitem></orderedlist>
<para>This search order places methods of a class before methods of its
superclasses so that a class can supplement or override inherited methods.
</para>
<para>If the language processor does not find a match for the message name, the
language processor checks the object for a method name UNKNOWN. If it exists,
the language processor calls the UNKNOWN method and returns as the message
result any result the UNKNOWN method returns. The UNKNOWN method arguments
are the original message name and a Rexx array containing the original message
arguments.</para>
<para>If the object does not have an UNKNOWN method, the language processor
raises a NOMETHOD condition. If there are no active traps for the NOMETHOD condition,
a syntax error is raised.
</para>
</section>
<section id="unkno"><title>Defining an UNKNOWN Method</title>
<para>When an object that receives a message does not have a matching message
name, the language processor checks if the object has a method named UNKNOWN.
If the object has an UNKNOWN method, the language processor calls UNKNOWN,
passing two arguments. The first argument is the name of the method that was
not located. The second argument is an array containing the arguments passed
with the original message.</para>
<para>For example, the following UNKNOWN method will print out the name of
the invoked method and then invoke the same method on another object. This
can be used track the messages that are sent to an object:</para>
<programlisting>
<![CDATA[
::method unknown
expose target -- will receive all of the messages
use arg name, arguments
say name "invoked with" arguments~toString
forward to(target) -- send along the message with the original args
]]>
</programlisting>
</section>
<section id="chsrod"><title>Changing the Search Order for Methods</title>
<indexterm><primary>search order</primary>
<secondary>for methods</secondary>
<tertiary>changing</tertiary></indexterm>
<indexterm><primary>changing the search order for methods</primary></indexterm>
<para>You can change the usual search order for methods by: </para>
<orderedlist>
<listitem><para>Ensuring that the receiver object is the sender object.
(You usually do this by specifying the special variable <link linkend="xself">SELF</link>.)
</para></listitem>
<listitem><para>Specifying a colon and a class symbol after the message name.
The class symbol can be a variable name or an environment symbol. It identifies
the class object to be used as the starting point for the method search.</para>
<para>The class object must be a superclass of the class defining the active
method, or, if you used SETMETHOD to define the active method, the object's own
class. The class symbol is usually the special variable SUPER
(see <link linkend="xsuper">SUPER</link>) but it can be any environment
symbol or variable name whose value is a valid class.</para></listitem>
</orderedlist>
<para>Suppose you create an Account class that is a subclass of the Object
class, define a TYPE method for the Account class, and create the Savings class
that is a subclass of Account. You could define a TYPE method for the Savings
class as follows: </para>
<programlisting>
savings~define("TYPE", &apos;return "a savings account"&apos;)
</programlisting>
<para>You could change the search order by using the following line: </para>
<programlisting>
savings~define("TYPE", &apos;return self~type:super "(savings)"&apos;)
</programlisting>
<para>This changes the search order so that the language processor searches for
the TYPE method first in the Account superclass (rather than in the Savings
subclass). When you create an instance of the Savings class
(<computeroutput>asav</computeroutput>)
and send a TYPE message to <computeroutput>asav</computeroutput>:</para>
<programlisting>
say asav~type
</programlisting>
<para><computeroutput>an account (savings)</computeroutput> is displayed.
The TYPE method of the Savings class calls the TYPE method of the Account
class, and adds the string <computeroutput>(savings)</computeroutput> to the
results.</para>
</section>
<section id="pubpri"><title>Public and Private Methods</title>
<indexterm><primary>method</primary>
<secondary>public</secondary></indexterm>
<indexterm><primary>method</primary>
<secondary>private</secondary></indexterm>
<indexterm><primary>public method</primary></indexterm>
<indexterm><primary>private method</primary></indexterm>
<para>A method can be public or private.
Any object can send a message that runs a public method.
A private method can only be invoked from specific calling contexts. These contexts are:</para>
<orderedlist>
<listitem><para>From within a method owned by the same class as the target. This is frequently
the same object, accessed via the special variable SELF. Private methods of an object can also
be accessed from other instances of the same class (or subclass instances).
</para></listitem>
<listitem><para>From within a method defined at the same class scope as the method. For example:</para>
<programlisting>
<![CDATA[
::class Savings
::method newCheckingAccount CLASS
instance = self~new
instance~makeChecking
return instance
::method makeChecking private
expose checking
checking = .true
]]>
</programlisting>
<para>The newCheckingAccount CLASS method is able to invoke the makeChecking method because
the scope of the makeChecking method is .Savings.
</para></listitem>
<listitem><para>From within an instance (or subclass instance) of a class to a private class
method of its class. For example:</para>
<programlisting>
<![CDATA[
::class Savings
::method init class
expose counter
counter = 0
::method allocateAccountNumber private class
expose counter
counter = counter + 1
return counter
::method init
expose accountNumber
accountNumber = self~class~allocateAccountNumber
]]>
</programlisting>
<para>The instance init method of the Savings class is able to invoke the allocateAccountNumber private
method of the .Savings class object because it is owned by an instance of the .Savings class.</para>
</listitem>
</orderedlist>
<para>Private methods include methods at different scopes within the same object.
This allows superclasses to make methods available to their subclasses while
hiding those methods from other objects. A private method is like an internal
subroutine. It shields the internal information of an object to outsiders, but allowing
objects to share information with each other and their defining classes.
</para>
</section>
<section id="creo"><title>Initialization</title>
<para>Any object requiring initialization at creation time must define an INIT
method. If this method is defined, the class object runs the INIT method after
the object is created. If an object has more than one INIT method (for example,
it is defined in several classes), each INIT method must forward the INIT
message up the hierarchy to complete the object's initialization.</para>
<para><emphasis role="bold">Example:</emphasis></para>
<programlisting>
asav = .savings~new(1000.00, 6.25)
say asav~type
asav~name = "John Smith"
::class Account
::method INIT
expose balance
use arg balance
::method TYPE
return "an account"
::method name attribute
::class Savings subclass Account
::method INIT
expose interest_rate
use arg balance, interest_rate
self~init:super(balance)
::method type
return "a savings account"
</programlisting>
<para>The NEW method of the Savings class object creates a new Savings object
and calls the INIT method of the new object. The INIT method arguments are
the arguments specified on the NEW method. In the Savings INIT method, the
line: </para>
<programlisting>
self~init:super(balance)
</programlisting>
<para> calls the INIT method of
the Account class, using just the balance argument specified on the NEW message.
</para>
</section>
<section id="obdes"><title>Object Destruction and Uninitialization</title>
<para>Object destruction is implicit. When an object is no longer in use, Rexx
automatically reclaims its storage. If the object has allocated other system
resources, you must release them at this time. (Rexx cannot release these
resources, because it is unaware that the object has allocated them.)</para>
<para>Similarly, other uninitialization processing may be needed, for example,
by a message object holding an unreported error. An object requiring
uninitialization
should define an UNINIT method. If this method is defined, Rexx runs it before
reclaiming the object's storage. If an object has more than one UNINIT method
(defined in several classes), each UNINIT method is responsible for sending
the UNINIT method up the object hierarchy.</para>
</section>
<section id="reqstr"><title>Required String Values</title>
<para>Rexx requires a string value in a number of contexts within instructions
and built-in function calls. </para>
<itemizedlist>
<listitem><para>DO statements containing
<emphasis role="italic">exprr</emphasis> or
<emphasis role="italic">exprf</emphasis></para></listitem>
<listitem><para>Substituted values in compound variable names</para></listitem>
<listitem><para>Commands to external environments</para></listitem>
<listitem><para>Commands and environment names on ADDRESS instructions
</para></listitem>
<listitem><para>Strings for ARG, PARSE, and PULL instructions to be parsed
</para></listitem>
<listitem><para>Parenthesized targets on CALL instructions</para></listitem>
<listitem><para>Subsidiary variable lists on DROP, EXPOSE, and PROCEDURE
instructions</para></listitem>
<listitem><para>Instruction strings on INTERPRET instructions</para></listitem>
<listitem><para>DIGITS, FORM, and FUZZ values on NUMERIC instructions</para>
</listitem>
<listitem><para>Options strings on OPTIONS instructions</para></listitem>
<listitem><para>Data queue strings on PUSH and QUEUE instructions</para>
</listitem>
<listitem><para>Label names on SIGNAL VALUE instructions</para></listitem>
<listitem><para>Trace settings on TRACE VALUE instructions</para></listitem>
<listitem><para>Arguments to built-in functions</para></listitem>
<listitem><para>Variable references in parsing templates</para></listitem>
<listitem><para>Data for PUSH and QUEUE instructions to be processed</para>
</listitem>
<listitem><para>Data for the SAY instruction to be displayed</para></listitem>
<listitem><para>Rexx dyadic operators when the receiving object (the object to
the left of the operator) is a string</para></listitem></itemizedlist>
<para>If you supply an object other than a string in these contexts, by default
the language processor converts it to some string representation and uses
this. However, the programmer can cause the language processor to raise the
NOSTRING condition when the supplied object does not have an equivalent string
value.</para>
<para>To obtain a string value, the language processor sends a REQUEST("STRING")
message to the object. Strings and other objects that have string values return
the appropriate string value for Rexx to use. (This happens automatically
for strings and for subclasses of the String class because they inherit a
suitable MAKESTRING method from the String class.) For this mechanism to work
correctly, you must provide a MAKESTRING method for any other objects with
string values.</para>
<para>For other objects without string values (that is, without a MAKESTRING
method), the action taken depends on the setting of the NOSTRING condition
trap. If the NOSTRING condition is being trapped (see
<link linkend="condtra">Conditions and Condition Traps</link>),
the language processor raises the NOSTRING condition. If the NOSTRING condition
is not being trapped, the language processor sends a STRING message to the
object to obtain its readable string representation (see the STRING method
of the Object class <link linkend="mthObjectString">STRING</link>) and uses this string.
</para>
<para>When comparing a string object with the Nil object, if
the NOSTRING condition is being trapped, then</para>
<programlisting>
if string = .nil
</programlisting>
<para>will raise the NOSTRING condition, whereas</para>
<programlisting>
if .nil = string
</programlisting>
<para>will not as the Nil object's "=" method does not expect
a string as an argument.</para>
<para><emphasis role="bold">Example:</emphasis></para>
<programlisting>
d = .directory~new
say substr(d,5,7) /* Produces "rectory" from "a Directory" */
signal on nostring
say substr(d,5,7) /* Raises the NOSTRING condition */
say substr(d~string,3,6) /* Displays "Direct" */
</programlisting>
<para>For arguments to Rexx object methods, different rules apply. When a
method expects a string as an argument, the argument object is sent the
REQUEST("STRING") message. If REQUEST returns the Nil object, then the
method raises an error.</para>
</section>
<section id="concurr"><title>Concurrency</title>
<para>Rexx supports concurrency, multiple methods running
simultaneously on a single object. See
<link linkend="xconcur">Concurrency</link> for a full
description of concurrency.</para>
</section>
</section>
<section id="classmeth"><title>Overview of Classes Provided by Rexx</title>
<para>This section gives a brief overview of the classes and methods
Rexx defines.</para>
<section id="chi"><title>The Class Hierarchy</title>
<para>Rexx provides the following classes belonging to the object class:</para>
<itemizedlist>
<listitem><para>Alarm class</para></listitem>
<listitem><para>Array class</para></listitem>
<listitem><para>Class class</para></listitem>
<listitem><para>Collection class</para>
<itemizedlist>
<listitem><para>MapCollection class</para></listitem>
<listitem><para>OrderedCollection class</para></listitem>
<listitem><para>SetCollection class</para></listitem>
</itemizedlist></listitem>
<listitem><para>Comparable class</para></listitem>
<listitem><para>Orderable class</para></listitem>
<listitem><para>Comparator class</para>
<itemizedlist>
<listitem><para>CaselessColumnComparator class</para></listitem>
<listitem><para>CaselessComparator class</para></listitem>
<listitem><para>CaselessDescendingComparator class</para></listitem>
<listitem><para>ColumnComparator class</para></listitem>
<listitem><para>DescendingComparator class</para></listitem>
<listitem><para>InvertingComparator class</para></listitem>
</itemizedlist></listitem>
<listitem><para>DateTime class</para></listitem>
<listitem><para>Directory class</para>
<itemizedlist>
<listitem><para>Properties class</para></listitem>
</itemizedlist></listitem>
<listitem><para>InputOutputStream class</para>
<itemizedlist>
<listitem><para>Stream class</para></listitem>
</itemizedlist></listitem>
<listitem><para>InputStream class</para></listitem>
<listitem><para>List class</para></listitem>
<listitem><para>Message class</para></listitem>
<listitem><para>Method class</para></listitem>
<listitem><para>Method class</para></listitem>
<listitem><para>Routine class</para></listitem>
<listitem><para>MutableBuffer class</para></listitem>
<listitem><para>OutputStream class</para></listitem>
<listitem><para>Queue class</para>
<itemizedlist>
<listitem><para>CircularQueue class</para></listitem>
</itemizedlist></listitem>
<listitem><para>RegularExpression class</para></listitem>
<listitem><para>Relation class</para>
<itemizedlist>
<listitem><para>Bag class</para></listitem>
</itemizedlist></listitem>
<listitem><para>RexxQueue class</para></listitem>
<listitem><para>Stem class</para></listitem>
<listitem><para>String class</para></listitem>
<listitem><para>Supplier class</para>
<itemizedlist>
<listitem><para>StreamSupplier class</para></listitem>
</itemizedlist></listitem>
<listitem><para>Table class</para>
<itemizedlist>
<listitem><para>Set class</para></listitem>
</itemizedlist></listitem>
<listitem><para>IdentityTable class</para></listitem>
<listitem><para>TimeSpan class</para></listitem>
<listitem><para>WeakReference class</para></listitem>
<listitem><para>RexxContext class</para></listitem>
<listitem><para>Buffer class</para></listitem>
<listitem><para>Pointer class</para></listitem>
</itemizedlist>
<para>(The classes are in a class hierarchy with subclasses indented below their
superclasses.)</para>
<para>Note that there might also be other classes in the system, depending
on the operating system. Additional classes may be accessed by using an
appropriate ::requires directive to load the class definitions.</para>
<para>The following figures show Rexx built-in classes.</para>
<figure float="1">
<title id="meths1">Classes and Inheritance (part 1 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="ooRexxClasses1" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths2">Classes and Inheritance (part 2 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="ooRexxClasses2" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths3">Classes and Inheritance (part 3 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="ooRexxClasses3" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths4">Classes and Inheritance (part 4 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="ooRexxClasses4" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths5">Classes and Inheritance (part 5 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="ooRexxClasses5" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths6">Classes and Inheritance (part 6 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<imagedata fileref="ooRexxClasses6" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths7">Classes and Inheritance (part 7 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<imagedata fileref="ooRexxClasses7" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths8">Classes and Inheritance (part 8 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<imagedata fileref="ooRexxClasses8" scale="90">
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths9">Classes and Inheritance (part 9 of 9)</title>
<mediaobject>
<imageobject>
<!-- Note! - if we include a /imagedata tag we get an error for DSSSL! -->
<imagedata fileref="ooRexxClasses9" scale="90">
</imageobject>
</mediaobject>
</figure>
</section>
<section id="methodsbyclass"><title>Class Library Notes</title>
<para>The chapters that follow describe the classes and other objects that Rexx
provides and their available methods. Rexx provides the objects listed in
these sections and they are generally available to all methods through
environment symbols (see <link linkend="ensym">Environment Symbols</link>).
</para>
<para><emphasis role="bold">Notes:</emphasis></para>
<orderedlist>
<listitem><para>In the method descriptions in the chapters that follow, methods
that return a result begin with the word "returns".</para></listitem>
<listitem><para>For [] and []= methods, the syntax diagrams include
the index or indexes within the brackets. These diagrams are intended to show
how you can use these methods. For example, to retrieve the first element
of a one-dimensional array named Array1, you would typically use the syntax:</para>
<programlisting>
Array1[1]
</programlisting>
<para>rather than:</para>
<programlisting>
Array1~&quot;[]&quot;(1)
</programlisting>
<para>
even though the latter is valid and equivalent. For more information,
see <link linkend="mssg">Message Terms</link> and
<link linkend="msgit">Message Instructions</link>.</para></listitem>
<listitem><para>When the argument of a method must be a specific kind of object (such
as array, class, method, or string) the variable you specify must be of the
same class as the required object or be able to produce an object of the
required kind in response to a conversion message. In particular, subclasses
are acceptable in place of superclasses (unless overridden in a way that
changes superclass behavior), because they inherit a suitable conversion method
from their Rexx superclass.</para>
<para>The <link linkend="mthObjectIsA">isA method</link> of the Object class
can perform this validation.
</para></listitem>
</orderedlist>
</section>
</section>
</chapter>