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

> ## Assignment and the CAST function

> As described in the previous section, you can assign a source object reference to a target object reference if the target object reference is defined as the same class, a super class, or an interface of the source object. When the target object reference is for a super class or interface an implicit cast is done by Progress at run time. The word cast, as used in object-oriented terminology, can be compared to the cast of a play, in which each actor is assigned a role. When you program with classes, each reference to an object must identify the role that the object is required to play, as identified by its class type. The compiler verifies that no object reference is allowed to act contrary to its assigned role and access a method or data member not defined by its class type.

> However, sometimes you might want to restrict the use of an object reference to a subset of the methods and data members defined by its class. When you use an object reference to a super class that actually points to an instance of one of its subclasses, you are then restricting object access to the methods and data members defined by the super class, even though the object instance might actually contain additional subclass methods and data members. Thus, restricting an object reference to the role of a super class assures that the reference can satisfy the minimum access requirements provided for the object by the super class while at the same time preventing any reference to the additional subclass state and behavior that the object might contain. In other words, using a super class object reference provides an additional level of information hiding for the subclass instance.

> Similarly, an interface defines at least some of the methods that a class implements. Thus, assigning an object reference from a class to an interface that the class type implements assures that the object reference enforces access only to implemented methods in the class that are defined by the specified interface.

> Progress permits all of these assignments from a subclass reference to a super class reference and from an interface reference to an implementing-class reference, because the very definition of a subclass or implementing class guarantees that `PUBLIC` data members and methods provided by the respective super class and interface object references will work. For example, refer to the following class hierarchy:

>     Progress.Lang.Object                  <--- Top of hierarchy
>         acme.myObjs.Common.CommonObj
>             acme.myObjs.CustObj
>                 acme.myObjs.NECustomer    <--- Bottom of hierarchy

> You can assign an `acme.myObjs.NECustomer` object reference to either an `acme.myObjs.CustObj`, `acme.myObjs.Common.CommonObj` or `Progress.Lang.Object` object reference. You can also assign an `acme.myObjs.CustObj` object reference to an `acme.myObjs.Common.CommonObj` or `Progress.Lang.Object` object reference.

> Sometimes it is necessary to cast downward—that is, to take an object reference for a super class or interface in a class hierarchy and assign it to an object reference defined for a subclass or interface-implementing class further down the class hierarchy. As noted, the compiler will not do this implicitly when you perform an assignment or pass a parameter, because it cannot verify that references to the object will all be valid. Therefore, you must cast an object reference downward explicitly using the `CAST` function. In addition, you cannot assign an object reference for an interface to an object reference for a class, even if the class implements the interface. To do this you must also use the `CAST` function.

> You can only cast an object reference downward when the object was originally instantiated as the target class or one of its subclasses. This means that you must know that a super class object reference, at run time, is really an object reference to a subclass or that an interface object reference is really an object reference to an interface-implementing class.

> Casting tells the compiler to trust your judgement and allow the downward cast within the specified class hierarchy. However, Progress checks at run time to ensure that a cast is valid. For example, if a super class object reference is not referring to an instance of the specified subclass, Progress returns a run-time error. This means that when you use the `CAST` function, you are bypassing some of the compiler's checks for validity of object references. This increases the flexibility of how you can assemble different classes and let them interoperate, but with your increased responsibility for making sure that all types are valid at run time.

> You can thus use the `CAST` function wherever an object reference is permitted:

> - To assign an object reference to another, especially when assigning a super class or interface reference to subclass or implementing class reference, respectively.

> - To pass an `INPUT` parameter to a method as a subclass type during the invocation of the method.

> - To invoke a method on a subclass of a specified object reference. You can do this by implicitly using the return value of the `CAST` function as the new object reference on which to invoke the method.

> Syntax descriptions for each of these uses of the `CAST` function follow.

> This is the syntax for the `CAST` function used to assign one object reference to another:

> Syntax
>     target-object-reference = CAST ( object-reference , target-type-name )

> This is the syntax for the `CAST` function used to pass an `INPUT` object reference parameter:

> Syntax
>      routine-name ( [ INPUT ] CAST ( object-reference , target-type-name ) )

> This is the syntax for the `CAST` function used to cast an object reference for a method call:

> Syntax
>     CAST ( object-reference , target-type-name ) : method-name ( ... )

> Element descriptions for these syntax diagrams follow:

> ``target-object-reference``

> A destination object reference, typically to one of the following:

> - A subclass of a class type `object-reference`.
> - An interface-implementing class of an interface type `object-reference`.
> ``object-reference``

> A source object reference, typically to a super class or interface of `target-object-reference`. This can be a variable or it can be a temp-table field defined as `Progress.Lang.Object.` At run time, Progress verifies that `object-reference` in fact refers to an instance of the specified `target-type-name`.

> ``target-type-name``

> A quoted string specifying the target class type name for the cast. This class type name must be the same as the class type name used to define `target-object-reference` or a subclass of the defining type name.

> ``routine-name``

> The name of any procedure, user-defined function, or method that takes an `INPUT` object reference parameter.

> ``method-name``

> The name of a method implemented by the class specified by `target-type-name`. The compiler verifies that `method-nam`e is a valid method defined in `target-type-name` and that the parameters (`(`...`)`) are valid.

> ##### Casting an object reference assignment

> For an example of assigning an object reference using the `CAST` function, see the "Defining an object reference as a field in a temp-table" section.

> ##### Casting an object reference parameter

> The following sample classes are use by the following examples to demonstrate the use of the `CAST` function to pass `INPUT` object reference parameters. The first sample class is a super class that defines nothing:

>     CLASS SuperClass:
>     END CLASS.

> The next sample class is a subclass that defines its own method, `subClassMethod( ):`

>     CLASS SubClass INHERITS SuperClass:
>         METHOD PUBLIC VOID subclassMethod ( ):
>         END METHOD.
>     END CLASS.

> Progress does not, by default, allow an object reference of `SuperClass` to be used as an instance of `SubClass`. For example, if you try to execute `subClassMethod( )` using the object reference to `SuperClass`, the method cannot be found. However, if you know that an object reference to `SuperClass` in reality points to an instance of `SubClass`, you can cast the reference as `SubClass` to use it.

> The following example demonstrates the use of the `CAST` function to pass an `INPUT` object reference parameter. The `Main` container class defines an object reference (`mySuper`) for the super class and a method (`subParmMethod( )`) that expects an object parameter of type `SubClass`, as shown:

>     CLASS Main:

>         DEFINE PRIVATE VARIABLE mySuper AS CLASS SuperClass NO-UNDO.
>         CONSTRUCTOR PUBLIC Main ( ):
>             mySuper = NEW SubClass ( ).
>             subParmMethod (INPUT CAST(mySuper, "SubClass")).
>         END CONSTRUCTOR.
>         METHOD PRIVATE VOID subParmMethod
>                 (INPUT myLocalSubClass AS CLASS SubClass):
>             myLocalSubClass:subClassMethod( ).
>         END METHOD.
>     END CLASS.

> In the previous example, the constructor instantiates a `SubClass` object, but assigns it to the `SuperClass` object reference. Using the `CAST` function, the constructor then invokes `subParmMethod( )`, passing the object reference as the `SubClass` parameter the method expects and that it actually is. The `subParmMethod( )` method then invokes the `subClassMethod( )` method on the passed object reference.

> ##### Casting an object reference to invoke a method

> The following example shows an alternative `Main` class used to access the sample classes `SuperClass` and `SubClass` defined in the previous example, this time to demonstrate the use of the `CAST` function to cast an object reference for a method call:

>     CLASS Main:

>         DEFINE PRIVATE VARIABLE mySuper AS CLASS SuperClass NO-UNDO.
>         CONSTRUCTOR PUBLIC Main ( ):
>             mySuper = NEW SubClass ( ).
>             CAST(mySuper, "SubClass"):subClassMethod ( ).
>         END CONSTRUCTOR.
>     END CLASS.

> In the previous example, the constructor sets the `SuperClass` object reference to a new `SubClass` instance, then invokes `subClassMethod( )` on the `SubClass` instance by casting the `SuperClass` object reference to `SubClass`.

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