[r9562]: / docs / trunk / rexxref / en-US / provide.xml  Maximize  Restore  History

Download this file

1032 lines (956 with data), 44.6 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
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "rexxref.ent">
%BOOK_ENTITIES;
]>
<!--#########################################################################
#
# Description: Open Object Rexx: Reference XML File
#
# Copyright (c) 2005-2012, 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.
#
#########################################################################
-->
<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 String class (<xref linkend="clsString" />) and the
Array class (<xref linkend="clsArray" />
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 ::CLASS directive (<xref linkend="clasdi" />.
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
Array class (<xref linkend="clsArray" />).
The statArray class can include a
method for computing a total of all the numeric elements of an array.</para>
<example>
<title>Creating an array subclass</title>
<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
/* <xref linkend="mthMessageNew" /> 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>
</example>
<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>
<example>
<title>Adding a CLASS method</title>
<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>
</example>
</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 <xref linkend="clsObject" /> 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 environment symbol (<xref linkend="ensym" />) used to locate your new class instance.
</para>
<para>Now you can use ::METHOD directive (<xref linkend="methd" />) to add methods to your new class. The
::METHOD directives must immediately follow the ::CLASS directive that creates
the class. </para>
<example>
<title>Adding a method</title>
<programlisting>
::method type
return "an account"
::method "name="
expose name
use arg name
::method name
expose name
return name
</programlisting>
</example>
<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>
<example>
<title>Adding a method</title>
<programlisting>
::class "Savings" subclass account
::method type
return "a savings account"
</programlisting>
</example>
<para>Now you can create an instance of the Savings class with the NEW method
(see <xref linkend="mthClassNew" />) and send TYPE, NAME, and NAME= messages
to that instance:</para>
<example>
<title>Invoking a method</title>
<programlisting>
asav = .savings~new
say asav~type
asav~name = "John Smith"
</programlisting>
</example>
<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>
<example>
<title>Defining SET and GET methods</title>
<programlisting>
::method "name="
expose name
use arg name
::method name
expose name
return name
</programlisting>
</example>
<para>You can replace this with a single ::ATTRIBUTE directive (<xref linkend="attrd" />.
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 ::CONSTANT directive (<xref linkend="constantd" />.
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>
<example>
<title>Retieving method values</title>
<programlisting>
say .Account~checkingMinimum -- displays "200"
asave = .savings~new
say asave~checkingMinimum -- also displays "200"
</programlisting>
</example>
<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 <xref linkend="mthObjectSetMethod" />) or ENHANCED (see
<xref linkend="mthClassEnhanced" />) 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>
<example>
<title>Accessing a method</title>
<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>
</example>
</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 <xref linkend="mthObjectSetMethod" /> .)</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
<xref linkend="mthClassInherit" />) 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>
<example>
<title>Defining an UNKNOWN method</title>
<programlisting>
<![CDATA[
::method unknown
expose target -- will receive all of the messages
use arg name, arguments
say name "invoked with" arguments~toString
-- send along the message with the original args
forward to(target) message(name) arguments(arguments)
]]>
</programlisting>
</example>
</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 SELF (<xref linkend="xself" />).
</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 <xref linkend="xsuper" />) 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>
<example>
<title>Referencing methods</title>
<programlisting>
<![CDATA[
::class Savings
::method newCheckingAccount CLASS
instance = self~new
instance~makeChecking
return instance
::method makeChecking private
expose checking
checking = .true
]]>
</programlisting>
</example>
<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>
<example>
<title>Referencing methods</title>
<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>
</example>
<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>
<example>
<title>Instance initialization</title>
<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>
</example>
<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>
<example>
<title>Instance initialization</title>
<programlisting>
self~init:super(balance)
</programlisting>
</example>
<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
<xref linkend="condtra" />),
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 STRING <xref linkend="mthObjectString" />) 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>
<example>
<title>Comparing to the .NIL object</title>
<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>
</example>
<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
<xref linkend="xconcur" /> 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>
<listitem><para>NumericComparator 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>File class</para></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>Monitor class</para></listitem>
<listitem><para>Routine class</para></listitem>
<listitem><para>MutableBuffer class</para></listitem>
<listitem><para>OutputStream class</para></listitem>
<listitem><para>Package 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>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses1.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths2">Classes and Inheritance (part 2 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses2.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths3">Classes and Inheritance (part 3 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses3.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths4">Classes and Inheritance (part 4 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses4.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths5">Classes and Inheritance (part 5 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses5.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths6">Classes and Inheritance (part 6 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses6.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths7">Classes and Inheritance (part 7 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses7.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths8">Classes and Inheritance (part 8 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses8.png" scale="90" />
</imageobject>
</mediaobject>
</figure>
<figure float="1">
<title id="meths9">Classes and Inheritance (part 9 of 9)</title>
<mediaobject>
<imageobject>
<!-- Warning!!!!! - if you modify this file it needs to be copied to the rexxpg! -->
<imagedata fileref="images/ooRexxClasses9.png" 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 <xref linkend="ensym" />).
</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 <xref linkend="mssg" /> and
<xref linkend="msgit" />.</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 isA method (<xref linkend="mthObjectIsA" />) of the Object class
can perform this validation.
</para></listitem>
</orderedlist>
</section>
</section>
</chapter>