Polymorphism

Rexx lets you send the same message to objects that are different:

"!iH"~reverse /* Reverses the characters "!iH" to form "Hi!" */
pen~reverse /* Reverses the direction of a plotter pen */
ball~reverse /* Reverses the direction of a moving ball */

As long as each object has its own REVERSE method, REVERSE runs even if the programming implementation is different for each object. This ability to hide different functions behind a common interface is called polymorphism. As a result of information hiding, each object in the previous example knows only its own version of REVERSE. And even though the objects are different, each reverses itself as dictated by its own code.

Although the !iH object's REVERSE code is different from the plotter pen's, the method name can be the same because Rexx keeps track of the methods each object owns. The ability to reuse the same method name so that one message can initiate more than one function is another feature of polymorphism. You do not need to have several message names like REVERSE_STRING, REVERSE_PEN, REVERSE_BALL. This keeps method-naming schemes simple and makes complex programs easy to follow and modify.

The ability to hide the various implementations of a method while leaving the interface the same illustrates polymorphism at its lowest level. On a higher level, polymorphism permits extensive code reuse.

Polymorphism involves a form of contract between two objects. One object will send a message to another object expecting a particular result. Different types of objects can implement different versions of this message as long as it fulfills the expectations of the invoking object. For example, the LOOP instruction has a form called OVER. Loop OVER will iterate over a number of elements provided by an object. For example,


LOOP OVER
myarray = .array~of("Rick", "David", "Mark")
loop name over myarray
say name
end

Will display the strings "Rick", "David", and "Mark", in that sequence. The LOOP OVER instruction will work with Array, List, Stem, Streams variables, etc. The LOOP instruction itself does not know anything about Arrays or Lists or Stems or Streams. The LOOP instruction specifies a contract. LOOP will send the target object the message MAKEARRAY and expects the target object to return an Array object that is used for the LOOP iteration. Any object can participate in LOOP iteration by implementing this contract. Objects that do implement the MAKEARRAY contract are polymorphic with the LOOP instruction.