Release 10.1A: OpenEdge Getting Started:
Object-oriented Programming

> ## Passing object reference parameters

> When an application passes an object reference to a method, user-defined function, or procedure, the effect is identical to assigning one object reference to another, with regard to the parameter mode (`INPUT`, `INPUT-OUTPUT`, or `OUTPUT`). Thus, the assignment rules can be summarized by designating the object that provides the reference as the source and the object that receives the reference as the target. The target object reference definition can be:

> 1. The same type as the source (for example, to `rCustObj` from `rCustObj`).

> 2. A super class of the source (for example, to `rCommonObj` from `rCustObj`).

> 3. An interface that the source implements (for example, to `rIBusObj` from `rCustObj`).

> For more information on the rules for assigning object references, see the "Assigning object references" section.

> Following are a series of examples that demonstrate the passing of object reference parameters for `INPUT`, `INPUT-OUTPUT`, and `OUTPUT`. These examples highlight code from the `Main` class shown previously (see the "Defining an object reference as a variable" section) and related sample classes that are described and fully listed in the "Sample classes" section. Refer to these samples for referenced class listings that are not shown in this section.

> When passing an `INPUT` parameter, the caller is the source of the assignment and the invoked method is the target of the assignment. Therefore, the invoked method must define a parameter that is the same class as the `INPUT` object reference, or a super class or interface of the `INPUT` object reference. If the invoked method has as its parameter a super class or interface object reference, the invoked method can only call those methods that are defined by that super class or interface. If the invoked method attempts to call methods that are not defined in the super class or interface, the compiler generates an error.

> The following examples pass an `INPUT` parameter:

>     CLASS Main:
>         DEFINE PRIVATE VARIABLE rCustObj
>             AS CLASS acme.myObjs.CustObj NO-UNDO.
>         ...
>         DEFINE PRIVATE VARIABLE rHelperClass
>             AS CLASS acme.myObjs.Common.HelperClass NO-UNDO.
>         ...
>         METHOD PUBLIC VOID ObjectInfo( ):
>             rHelperClass:ListDate(INPUT rCustObj).
>             MESSAGE rCustObj:timestamp.
>             ...
>         END METHOD.
>         ...
>     END CLASS.

>     CLASS acme.myObjs.Common.HelperClass:
>         METHOD PUBLIC VOID ListDate
>                 (INPUT rObject AS CLASS acme.myObjs.Common.CommonObj):
>             /* Timestamp this object */
>             IF VALID-OBJECT(rObject) THEN
>                 rObject:updateTimestamp( ).
>             ELSE
>                 rError:Alert("Not a valid object").
>         END METHOD.
>     END CLASS.

> The previous example shows an `acme.myObjs.CustObj` instance passed as input to the `ListDate( )` method, which is defined to take an `acme.myObjs.Common.CommonObj` (super class of `acme.myObjs.CustObj`). Note that the `updateTimestamp( )` method invoked on the input object reference only exists in `acme.myObjs.Common.CommonObj`. (For a listing of this class, see the "Calling methods from inside a class" section.) This method can be invoked on any object that is a subclass of `acme.myObjs.Common.CommonObj`. After the invocation of the method in `Main`, the program accesses the public data member `timestamp`, which is also defined in `acme.myObjs.Common.CommonObj`. For more information on `acme.myObjs.Common.CommonObj`, see the sample classes in the "Sample classes" section.

> When you pass an `INPUT-OUTPUT` object then the corresponding parameter must have the same class as the `INPUT-OUTPUT` object. Because the parameter is being passed in both directions, its type must match exactly.

> The following examples pass an `INPUT-OUTPUT` parameter:

>     CLASS Main:
>         DEFINE PRIVATE VARIABLE rCustObj
>             AS CLASS acme.myObjs.CustObj NO-UNDO.
>         ...
>         DEFINE PRIVATE VARIABLE rHelperClass
>             AS CLASS acme.myObjs.Common.HelperClass NO-UNDO.
>         ...
>         METHOD PUBLIC VOID ObjectInfo( ):
>             rHelperClass:ListNames(INPUT-OUTPUT rCustObj).
>             rCustObj:CheckCredit( ).
>             ...
>         END METHOD.
>         ...
>     END CLASS.

>     CLASS acme.myObjs.Common.HelperClass:
>         DEFINE PRIVATE VARIABLE rCustObj AS CLASS acme.myObjs.CustObj NO-UNDO.
>         ...
>         METHOD PUBLIC VOID ListNames
>                 (INPUT-OUTPUT prCustObj AS CLASS acme.myObjs.CustObj):
>             DEFINE VARIABLE i AS INTEGER NO-UNDO.
>             DO i = 1 to prCustObj:iNumCusts:
>                 CREATE ttCustNames.
>                 ASSIGN
>                     ttCustNames.CustName = prCustObj:GetCustomerName(INPUT i)
>                     ttCustNames.CustNum  = i.
>             END.
>             rCustObj = prCustObj.
>             prCustObj = NEW acme.myObjs.CustObj( ).
>         END METHOD.
>     END CLASS.

> The previous example shows an `acme.myObjs.CustObj` instance passed as an `INPUT-OUTPUT` parameter to the `ListNames( )` method in `acme.myObjs.Common.HelperClass`. In this case, the type on both sides (the passed object reference and the parameter definition) have to be exactly the same, in this case `acme.myObjs.CustObj`. The `ListNames( )` method first uses the input object reference and stores the value in its `PRIVATE` data member, `rCustObj`. Then, `ListNames( )` instantiates a new instance of `acme.myObjs.CustObj` to return as an output object reference with the same parameter, which is used back in the `Main` class to invoke the `CheckCredit( )` method defined in `acme.myObjs.CustObj`.

> When passing an `OUTPUT` parameter, the caller is the target of the assignment and the invoked method is the source of the assignment. Therefore, the caller method must define a parameter that is the same class as the `OUTPUT` object reference, or a super class or interface of the `OUTPUT` object reference. Once again, if the caller has as its parameter a super class or interface object reference, the caller can only invoke those methods that are defined by the super class or interface, respectively. If the caller attempts to invoke a method that is not defined in the super class, the compiler generates an error.

> The following examples pass an `OUTPUT` parameter:

>     CLASS Main:
>         ...
>         DEFINE PRIVATE VARIABLE rIBusObj
>             AS CLASS acme.myObjs.Interfaces.IBusObj NO-UNDO.
>         ...
>         DEFINE PRIVATE VARIABLE rHelperClass
>             AS CLASS acme.myObjs.Common.HelperClass NO-UNDO.
>         ...
>         METHOD PUBLIC VOID ObjectInfo( ):
>             rHelperClass:ReportOutput(OUTPUT rIBusObj).
>             rIBusObj:logObj(INPUT "Customer.out").
>             ...
>         END METHOD.
>         ...
>     END CLASS.

>     CLASS acme.myObjs.Common.HelperClass:
>         DEFINE PRIVATE VARIABLE rCustObj AS CLASS acme.myObjs.CustObj NO-UNDO.
>         ...
>         METHOD PUBLIC VOID ReportOutput
>                 (OUTPUT prInterface AS CLASS acme.myObjs.Interfaces.IBusObj):
>             /* Send the PRIVATE CustObj instance back to be printed */
>             IF VALID-OBJECT(rCustObj) THEN
>                 prInterface = rCustObj.
>             ELSE
>                 rError:Alert("The object is not valid").
>         END METHOD.
>     END CLASS.

> In the previous example, the `ReportOutput( )` method is invoked with an `OUTPUT` parameter defined as an object reference to the `acme.myObjs.Interfaces.IBusObj` interface. Through the `OUTPUT` parameter, the method in `acme.myObjs.Common.HelperClass` returns an object reference to `acme.myObjs.CustObj` (which happens to be privately maintained by the class). This works because `acme.myObjs.CustObj` implements the `acme.myObjs.Interfaces.IBusObj` interface. The class `acme.myObjs.Common.HelperClass` can return any object that implements `acme.myObjs.Interfaces.IBusObj`. Note that after returning from `ReportOutput( )`, the `logObj( )` method is invoked on the returned object reference. This method is specified in the interface and implemented in `acme.myObjs.CustObj`. It would be invalid to invoke a method on the returned object reference that is not specified in the interface.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095