PSL supports the ability to change the class of an instantiated object to its parent class, descendant class, or a compatible class. Compatible classes include String, Number, Date, Boolean, and Time. To reference the properties of a descendant class that are not in the parent class (e.g., DEP.BALAVL is not in the ACN table), the parent class must first be cast into the descendant. When an object is cast into another class, the original class is overwritten within the scope level of the cast.
The following rules govern casting objects in PSL:
A value of any data type can be cast to its own type.
Values of primitive data types are converted according to the to<type> method contained in the OBJECTMET table for the type being cast from. If this method does not exist, the value is not changed; however, the type is changed.
A value of any primitive data type cannot be cast to a reference data type.
A value of any reference data type cannot be cast to a primitive data type.
A reference to a class type can be cast to the ancestor (superclass) of that class.
The cast expression cannot be placed into a conditional expression, since logical conditions cannot be tested at compile time.
A reference to a class type can be cast to the type of a descendant (subclass) of that class if the reference actually refers to an object of the specified class or any of its subclasses. Generally, the compiler must generate a run-time test to verify that the object is of the appropriate type.
Example
A RecordACN object may be cast into either of its descendants, RecordDEP or RecordLN. However, a RecordDEP object cannot be cast as a RecordLN object or vice versa, because RecordLN is not a descendant or ancestor of RecordDEP.
If an ancestor class may conditionally be one or another of its descendants, the PSL source code should be structured as in the following code. In this example, because RecordACN is cast in a nested block, the scope of the cast is within the block and returns to the original scope when the block ends. The code blocks can also be optimized when the #OPTIMIZE qualifier is on, while passing objects into a subroutine disables code optimization.
#optimize
type Number BALANCE
type RecordACN acn = Db.getRecord("ACN","CID=:AREF")
if COMP = "%PCOL" set BALANCE = acn.balcol
else if acn.cls = "L" do {
set acn = {RecordLN}acn
set BALANCE = acn.avlbal
}
else do {
set acn = {RecordDEP}acn
set BALANCE = acn.balavl
}
quit BALANCE