This section illustrates how to access a class definition object and how to examine its properties to get information about the class, its scripts, and its variables.
To work with class information, you need a class definition object. There are two ways to get a ClassDefinition object containing class definition information.
For an instantiated object in your application
Use its ClassDefinition property.
For example, in a script for a button, this code gets the class definition for the parent window:
ClassDefinition cd_windef cd_windef = Parent.ClassDefinition
For an object stored in a PBL
Call FindClassDefinition.
For example, in a script for a button, this code gets the class definition for the window named w_genapp_frame from a library on the application's library list:
ClassDefinition cd_windef cd_windef = FindClassDefinition("w_genapp_frame")
This section has code fragments illustrating how to get information from a ClassDefinition object called cd_windef.
For examples of assigning a value to cd_windef, see Getting a class definition object.
Library
The LibraryName property reports the name of the library a class has been loaded from:
s = cd_windef.LibraryName
Ancestor
The Ancestor property reports the name of the class from which this class is inherited. All objects are inherited from PowerBuilder system objects, so the Ancestor property can hold a ClassDefinition object for a PowerBuilder class. The Ancestor property contains a null object reference when the ClassDefinition is for PowerObject, which is the top of the inheritance hierarchy.
This example gets a ClassDefinition object for the ancestor of the class represented by cd_windef:
ClassDefinition cd_ancestorwindef cd_ancestorwindef = cd_windef.Ancestor
This example gets the ancestor name. Note that this code would cause an error if cd_windef held the definition of PowerObject, because the Ancestor property would be NULL:
ls_name = cd_windef.Ancestor.Name
Use the IsValid function to test that the object is not NULL.
This example walks back up the inheritance hierarchy for the window w_genapp_frame and displays a list of its ancestors in a MultiLineEdit:
string s, lineend ClassDefinition cd lineend = "~r~n" cd = cd_windef s = "Ancestor tree:" + lineend DO WHILE IsValid(cd) s = s + cd.Name + lineend cd = cd.Ancestor LOOP mle_1.Text = s
The list might look like this:
Ancestor tree: w_genapp_frame window graphicobject powerobject
Parent
The ParentClass property of the ClassDefinition object reports the parent (its container) specified in the object's definition:
ClassDefinition cd_parentwindef cd_parentwindef = cd_windef.ParentClass
If the class has no parent, ParentClass is a null object reference. This example tests that ParentClass is a valid object before checking its Name property:
IF IsValid(cd_windef.ParentClass) THEN ls_name = cd_windef.ParentClass.Name END IF
Nested or child classes
The ClassDefinition object's NestedClassList array holds the classes the object contains.
NestedClassList array includes ancestors and descendants
The NestedClassList array can include classes of ancestor objects. For example, a CommandButton defined on an ancestor window and modified in a descendant window appears twice in the array for the descendant window, once for the window and once for its ancestor.
This script produces a list of the controls and structures defined for the window represented in cd_windef.
string s, lineend integer li lineend = "~r~n" s = s + "Nested classes:" + lineend FOR li = 1 to UpperBound(cd_windef.NestedClassList) s = s + cd_windef.NestedClassList[li].Name & + lineend NEXT mle_1.Text = s
This script searches the NestedClassList array in the ClassDefinition object cd_windef to find a nested DropDownListBox control:
integer li ClassDefinition nested_cd FOR li = 1 to UpperBound(cd_windef.NestedClassList) IF cd_windef.NestedClassList[li].DataTypeOf & = "dropdownlistbox" THEN nested_cd = cd_windef.NestedClassList[li] EXIT END IF NEXT
Class definitions for object instances as distinct from object references
Getting a ClassDefinition object for an instantiated object, such as an ancestor or nested object, does not give you a reference to instances of the parent or child classes. Use standard PowerBuilder programming techniques to get and store references to your instantiated objects.
This section has code fragments illustrating how to get script information from a ClassDefinition object called cd_windef.
For examples of assigning a value to cd_windef, see Getting a class definition object.
List of scripts
The ScriptList array holds ScriptDefinition objects for all the functions and events defined for a class. If a function is overloaded, it will appear in the array more than once with different argument lists. If a function or event has code at more than one level in the hierarchy, it will appear in the array for each coded version.
This example loops through the ScriptList array and builds a list of script names. All objects have a few standard functions, such as ClassName and PostEvent, because all objects are inherited from PowerObject:
string s, lineend integer li ScriptDefinition sd lineend = "~r~n" FOR li = 1 to UpperBound(cd_windef.ScriptList) sd = cd_windef.ScriptList[li] s = s + sd.Name + " " + lineend NEXT mle_1.Text = s
This example amplifies on the previous one and accesses various properties in the ScriptDefinition object. It reports whether the script is a function or event, whether it is scripted locally, what its return datatype and arguments are, and how the arguments are passed:
string s, lineend integer li, lis, li_bound ScriptDefinition sd lineend = "~r~n" FOR li = 1 to UpperBound(cd_windef.ScriptList) sd = cd_windef.ScriptList[li] s = s + sd.Name + " " CHOOSE CASE sd.Kind CASE ScriptEvent! // Events have three relevant properties // regarding where code is defined s = s + "Event, " IF sd.IsScripted = TRUE then s = s + "scripted, " END If IF sd.IsLocallyScripted = TRUE THEN s = s + "local, " END IF IF sd.IsLocallyDefined = TRUE THEN s = s + "local def," END IF CASE ScriptFunction! // Functions have one relevant property // regarding where code is defined s = s + "Function, " IF sd.IsLocallyScripted = TRUE THEN s = s + "local, " END IF END CHOOSE s = s + "returns " + & sd.ReturnType.DataTypeOf + "; " s = s + "Args: " li_bound = UpperBound(sd.ArgumentList) IF li_bound = 0 THEN s = s + "None" FOR lis = 1 to li_bound CHOOSE CASE sd.ArgumentList[lis]. & CallingConvention CASE ByReferenceArgument! s = s + "REF " CASE ByValueArgument! s = s + "VAL " CASE ReadOnlyArgument! s = s + "READONLY " CASE ELSE s = s + "BUILTIN " END CHOOSE s = s + sd.ArgumentList[lis].Name + ", " NEXT s = s + lineend NEXT mle_1.text = s
Where the code is in the inheritance hierarchy
You can check the IsLocallyScripted property to find out whether a script has code at the class's own level in the inheritance hierarchy. By walking back up the inheritance hierarchy using the Ancestor property, you can find out where the code is for a script.
This example looks at the scripts for the class associated with the ClassDefinition cd_windef, and if a script's code is defined at this level, the script's name is added to a drop-down list. It also saves the script's position in the ScriptList array in the instance variable ii_localscript_idx. The DropDownListBox is not sorted, so the positions in the list and the array stay in sync:
integer li_pos, li FOR li = 1 to UpperBound(cd_windef.ScriptList) IF cd_windef.ScriptList[li].IsLocallyScripted & = TRUE THEN li_pos = ddlb_localscripts.AddItem( & cd_windef.ScriptList[li].Name) ii_localscript_idx[li_pos] = li END IF NEXT
Matching function signatures
When a class has overloaded functions, you can call FindMatchingFunction to find out what function is called for a particular argument list.
For an example, see FindMatchingFunction in the PowerScript Reference.
This section has code fragments illustrating how to get information about variables from a ClassDefinition object called cd_windef. For examples of assigning a value to cd_windef, see Getting a class definition object.
List of variables
Variables associated with a class are listed in the VariableList array of the ClassDefinition object. When you examine that array, you find not only variables you have defined explicitly but also PowerBuilder object properties and nested objects, which are instance variables.
This example loops through the VariableList array and builds a list of variable names. PowerBuilder properties appear first, followed by nested objects and your own instance and shared variables:
string s, lineend integer li VariableDefinition vard lineend = "~r~n" FOR li = 1 to UpperBound(cd_windef.VariableList) vard = cd_windef.VariableList[li] s = s + vard.Name + lineend NEXT mle_1.Text = s
Details about variables
This example looks at the properties of each variable in the VariableList array and reports its datatype, cardinality, and whether it is global, shared, or instance. It also checks whether an instance variable overrides an ancestor declaration:
string s integer li VariableDefinition vard lineend = "~r~n" FOR li = 1 to UpperBound(cd_windef.VariableList) vard = cd_windef.VariableList[li] s = s + vard.Name + ", " s = s + vard.TypeInfo.DataTypeOf CHOOSE CASE vard.Cardinality.Cardinality CASE ScalarType! s = s + ", scalar" CASE UnboundedArray!, BoundedArray! s = s + ", array" END CHOOSE CHOOSE CASE vard.Kind CASE VariableGlobal! s = s + ", global" CASE VariableShared! s = s + ", shared" CASE VariableInstance! s = s + ", instance" IF vard.OverridesAncestorValue = TRUE THEN s = s + ", override" END IF END CHOOSE s = s + lineend NEXT mle_1.text = s