PARAMETERS example
The following contrived examples demonstrate the various aspects of the parameter passing mechanism. With the following program file, DOUBLE.PRG:
parameters arg
arg *= 2 // Double passed parameter
from the Command window, typing the following statements results in the values shown in the comments:
x = 7
double( x ) // Call as variable
? x // Displays 14, pass by reference
double( x + 0 ) // Call as an expression
? x // Displays 14, pass by value
double( (x) ) // Call with parentheses around variable name
? x // Displays 14, pass by value
o = new Object( )
o.x = 5
double( o.x ) // Call as property
? o.x // Displays 10, pass by reference
double( (o.x) ) // Call with parentheses around property name
? o.x // Displays 10, pass by value
With the following program DOUBLEX.PRG, designed specifically to modify the property x of the passed object:
parameters oArg
oArg.x *= 2
typing the following statements in the Command window results in the values shown in the comments:
doublex( o ) // Pass by reference
? o.x // Displays 10, property modified
doublex( (o) ) // Pass by value
? o.x // Displays 20, property still modified
With the following program ILIKEAPP.PRG:
parameter oArg
oArg := _app
passing by value will prevent the object reference itself from being changed:
f = new Form( )
ilikeapp( (f) ) // Pass by value
? f.className // Displays FORM
ilikeapp( f ) // Pass by reference
? f.className // Displays APPLICATION, object reference changed
g = "test" // Another variable, this one with a string
ilikeapp( g ) // Pass by reference
? g.className // Displays APPLICATION, variable changed to an object reference
Note that you when assigning to a variable that was passed by reference, you are free to change the type of the variable.
This example demonstrates what happens if you don’t enclose the special object reference this in parentheses when it is passed to the method of another object. (Codeblocks are used for the methods; codeblocks declare their parameters in-between pipe characters instead of using a PARAMETERS statement.)
f = new Form( "F" ) // text property is "F"
g = new Form( "G" ) // text property is "G"
f.test1 = {; g.meth( this )} // Pass-by-reference
f.test2 = {; g.meth( (this) )} // Pass-by-value
g.meth = {|o|; ? o.text} // Display text property of passed object
f.test1( ) // Pass-by-reference displays "G"
f.test2( ) // Pass-by-value displays "F"
Whenever an object’s method is called, the value of this is automatically updated to point to that object. If the parameter this is passed by reference from the caller, the value of this changes to the called object before it is assigned to the parameter variable. By enclosing the parameter this in parentheses to make it pass-by-value, this does not change, and the parameter value is passed as expected.