DEFINE PROPERTY statement
- Last Updated: February 11, 2026
- 23 minute read
- OpenEdge
- Version 13.0
- Documentation
Defines a property of a class, declares a property prototype in an ABL interface, or overrides a property inherited from an ABL or .NET super class. A property is a named member of a class that allows you to read or write a value using the same syntax as a data member. However, a property can define special methods (accessors) that specify if and how the property can be read or written.
.cls) file.Syntax
Use the following syntax for defining a property that you can both read and write:
|
Use the following syntax to define a property that you can read only:
|
Use the following syntax to define a property that you can write only:
|
Use the following syntax to declare an interface property prototype:
|
Use the following syntax to declare an abstract property prototype:
|
- [ PRIVATE | PACKAGE-PRIVATE | PROTECTED | PACKAGE-PROTECTED | PUBLIC ]
-
Specifies the access mode for the property. A
PRIVATEproperty can be accessed by the defining class. An instance can access a private property of another instance if both instances are of the same class. APACKAGE-PRIVATEproperty can be accessed from within the class and any class within its package. APROTECTEDproperty can be accessed by the defining class and any of its derived classes. APACKAGE-PROTECTEDproperty can be accessed from within the class, any class within its package, and from within any subclass that inherits the class. APUBLICproperty can be accessed from any code (in a class or a procedure) that has access to a class instance.The default access mode is
PUBLIC.This access mode applies to both reading and writing the property value by default. However, you can set a different access mode for reading or writing the property value (but not both) using an appropriate accessor-access-mode option to define the corresponding accessor (
GETorSET).When declaring an interface property prototype, the access mode for the property must be
PUBLIC(the default).When defining an abstract property, the access mode for the property cannot be
PRIVATE. - [ STATIC ]
- Defines a property that is a static member of the class type for
which it is defined and that is scoped to the ABL session where it is referenced. ABL
creates one copy of the specified class static property on first reference to the class
type, and ABL creates only one such copy for any number of instances of the class that
you create. You can reference an accessible static property in any piece of code.
Without this option, ABL defines an instance property that is scoped to a single instance of the class where it is defined. ABL creates one copy of the specified instance property for each such class instance that you create. You can reference any public instance property (non-abstract) in any procedure, or in any instance or static method defined inside or outside of the class where the instance property is defined. Any static method can reference the public instance property only using an object reference to a class instance that defines the property as a member. If the referencing static method is defined in the same class as the public instance property, the class must instantiate itself in order to have access to an instance reference.
For more information on the mechanism for accessing properties of different access modes and scopes, see the reference entry for Class-based property access.
The
STATICoption is not valid when you:- Define or implement an abstract property
- Declare an interface property prototype
- Implement an interface property
Note: The access mode modifier and theSTATIC/ABSTRACTmodifier can appear in either order, e.g.,DEFINE STATIC PUBLIC myProperty PROPERTY...is valid syntax. - [ ABSTRACT ]
- Defines the property as an abstract member of the class type for
which it is defined. The defining class type must also be abstract. If you define an
abstract property, it has the following requirements:
- You must specify the
OVERRIDEoption if an inherited abstract property has the same name and data type. - You can specify any access mode other than
PRIVATE. - The abstract property must be overridden and implemented in a derived class.
Any class definition for an instance property that includes the
OVERRIDEoption and does not include theABSTRACToption defines a property implementation. If it also includes theABSTRACToption, the inherited abstract property remains abstract.This option is not valid either when you define a static property or when you declare an interface property prototype.
- You must specify the
- [ FINAL ]
- Indicates that this property cannot be overridden.
This option is not valid when you define a static or abstract property or when you declare an interface property prototype.
- [ OVERRIDE ]
- Specifies that this instance property
overrides a property inherited from an ABL or .NET property.
When you specify
OVERRIDE, the property definition must match the inherited property with respect to name, data type (including array dimensions), specified accessors (GETorSET), andNO-UNDOsetting. In addition, the access mode must not be more restrictive than the access mode defined for the overridden property. When overriding a .NET property, the data type must also map appropriately to the inherited .NET property data type. For more information, see the description of the primitive-type-name and object-type-name options. - [ SERIALIZABLE | NON-SERIALIZABLE ]
- Class-based objects that are defined as serializable (using the
SERIALIZABLEoption in the CLASS statement) can be passed as parameters in remotes call between the application server and ABL clients and can be serialized to binary or JSON format. By default, both passing a class as a parameter and serializing an object to binary via theProgress.IO.BinarySerializerclass include all data members regardless of access mode. However, for JSON serialization viaProgress.IO.JsonSerializer, only public data members are serialized. To include a non-public property during JSON serialization,SERIALIZABLEmust be added to the definition. See Serialize( ) method (JsonSerializer) for more information. - property-name
- Specifies the name of the property. The property-name must be unique among the names of all properties, events, and
variable data members that are defined in the class and its inherited class hierarchy
(not counting abstract member overrides) and that are accessible to the defining class
(not defined as
PRIVATEin a super class).Note: Members of a class are grouped into six namespaces, including buffers/temp-tables, methods, variables/properties/events, ProDataSets, queries, and data-sources. Variables, properties, and events defined as members of a class share the same namespace. There can be only one class member in this namespace with a given name (not counting abstract member overrides).You can reference this name from outside the property definition in order to read a value from or write a value to the property. You can reference this name from inside the property definition (in a
GETorSETaccessor) in order to read or write the value of the default memory for the property, according to its data type.Note: If the property is defined in a class that is derived from a .NET class, other restrictions on property-name apply. For more information, see the CLASS statement reference entry. - AS primitive-type-name
- Specifies a built-in primitive type (primitive-type-name) and an optional initial value (constant) for the default memory of the property. The
built-in data type can be one of the following:
CHARACTER | COM-HANDLE | DATE | DATETIME | DATETIME-TZ | DECIMAL | HANDLE | INT64 | INTEGER| LOGICAL | LONGCHAR | MEMPTR | RAW | RECID | ROWID | AS-data-typeIf you are overriding a .NET abstract property or implementing a property defined in a .NET interface, primitive-type-name must specify the exact same .NET mapped data type that is defined for the corresponding .NET property. For a .NET mapped data type that is a default match for a given ABL primitive type, you must use the default matching ABL data type, as shown in Table 4. (For example,
INTEGERindicates a .NET System.Int32.) For a .NET mapped data type that is not a default match for one of the ABL primitive types, ABL provides a data type keyword (AS-data-type) that you must use to explicitly indicate the required .NET data type, as shown in Table 5. (For example, the AS data type, UNSIGNED-BYTE, indicates a .NET System.Byte.)Note: At run time, a property defined using an AS-data-type keyword behaves in ABL like the corresponding ABL primitive type shown in Table 5. (For example, an UNSIGNED-BYTE behaves like an INTEGER.)Also note that when implementing a .NET array property, you must specify the .NET array object type (for example,
"System.Int32[]"or"System.Byte[]"); you cannot use an ABL array equivalent (such as INTEGER EXTENT or UNSIGNED-BYTE EXTENT).These are the same set of primitive types that can be specified for the return type of a method. Thus, for example, a property cannot have a complex type such as a temp-table, ProDataSet, or any other data type that is invalid as a method return type. For more information on these primitive types, see the Data types reference entry.
Note: To manage public access for a complex data type that cannot be specified for a property, you can define both a data member of that complex type and a separate public method that passes the complex type as a parameter. - AS [ CLASS ]object-type-name
- Specifies an object reference with the data type of a class or
interface for the default memory of the property. The default value of the property is
the Unknown value (
?). You cannot assign an initial value using theINITIALoption.- object-type-name
- Specifies the type name of an ABL or .NET class or interface.
Specify an object type name using the syntax described in the Type-name syntax reference entry. With an
appropriate USING statement,
you can also specify a class or interface name alone, without the qualifying
package or namespace.
You cannot directly specify the type name of a .NET mapped object type (such as System.Int32). To define a property that matches a .NET mapped type, you must define it as the corresponding ABL primitive type (primitive-type-name).
If you are overriding a .NET abstract property or implementing a property defined in a .NET interface, object-type-name must specify the exact same .NET object type as the corresponding interface property. However, for .NET inner (nested) type, note the difference in the ABL syntax, which replaces the corresponding period (.) in the .NET object type with a plus (+) (see the Type-name syntax reference entry).
Also note that when implementing a .NET array property, you must specify the exact .NET array object type (for example,
"System.Drawing.Point[]"); you cannot use an ABL array equivalent (such as System.Drawing.Point EXTENT). - CLASS
- If the specified class or interface type name conflicts with
an abbreviation of a built-in primitive type name, such as INT for INTEGER, you
must specify the CLASS keyword.
For more information on object references, see the Class-based object reference reference entry.
- [ EXTENT [ constant ]]
- Defines the property as an array of data elements, where the element
data type is specified by either the AS primitive-type-name option or the AS object-type-name option. This option can specify an array property as
either determinate (has a defined number of elements) or indeterminate (has an undefined
number of elements). To define a determinate array property, specify the
EXTENToption with the constant argument. This optional argument is an integer value that represents the number of elements in the property array. To define an indeterminate array property, specify theEXTENToption without the constant argument.The
EXTENTis part of the property data type. For more information, see the Type-name syntax reference entry.For more information about arrays, see Work with one-dimensional arrays in Basic ABL.
If you do not use the
EXTENToption (or you specify constant as 0), the property is not an array property. - [ INITIAL {constant| [ constant[ , constant] . . . ] }]
- The initial value of the property you want to define. If you use the
AS primitive-type-nameoption and you do not use theINITIAL constantoption, the initial value is the default initial value for the data type of the variable or array element.Note: Using Scientific notation format is allowed for DECIMAL, INTEGER, and INT64 types.When you define an array property, you can supply initial values for each element in the array. For example:
DEFINE PUBLIC PROPERTY pbarray-var AS AS CHARACTER EXTENT 3 INITIAL ["Add","Delete","Update"] GET. SET.If you do not supply enough values to fill up the elements of the array, the AVM puts the last value you named into the remaining elements of the array. If you supply too many values, the AVM raises an error.
If you define a property as an indeterminate array, and you supply initial values for elements in the array, the AVM sets the number of elements and treats the array as a determinate array.
The
INITIALoption is not valid either when you define an abstract property or when you declare an interface property prototype.The following table lists the default initial values for the various property data types.
Table 1. Default variable initial values Data type Default initial value CHARACTER "" (an empty string) CLASS*, ** Unknown value ( ?)COM-HANDLE** Unknown value ( ?)DATE Unknown value ( ?) (displays as blanks)DATETIME Unknown value ( ?)DATETIME-TZ Unknown value ( ?)DECIMAL 0 HANDLE** Unknown value ( ?)INT64 0 INTEGER 0 LOGICAL no LONGCHAR Unknown value ( ?)MEMPTR** A zero-length sequence of bytes RAW** A zero-length sequence of bytes RECID Unknown value ( ?)ROWID** Unknown value ( ?)* If you display a class instance using the MESSAGE statement, ABL automatically invokes the ToString( ) method (Object) (provided by the Progress.Lang.Object class) on the object reference. To display a class instance in a frame (for example, using the DISPLAY statement), you must first explicitly convert the object reference to a displayable type using the INT64 function, the INTEGER function, the STRING function, or the ToString( ) method (Object).
** You cannot use the INITIAL option to specify an initial value for this data type as part of the property definition.
- SERIALIZE-NAME serialize-name
- An optional CHARACTER constant that specifies the name of the property as it should appear when serialized into JSON. The default is property-name. Use this option when the serialized name contains invalid characters for an ABL name, is an ABL keyword, or an invalid JSON property name.
- [ NO-UNDO ]
- When the value of a property is changed during a transaction and the
transaction is undone, the AVM restores the value of the property to its prior value. If
you do not want, or if you do not need, the value of such a property to be undone even
when it has been changed during a transaction, use the
NO-UNDOoption.NO-UNDOproperties are more efficient; use this option whenever possible. - [ accessor-access-mode ]
- Specifies the access mode for the immediately following accessor
(
GETorSET). The possible access modes include:PACKAGE-PROTECTED | PROTECTED | PACKAGE-PRIVATE | PRIVATETo use an accessor-access-mode with accessors:
- You must define at least one accessor (GET or SET) that defaults to the access mode of the property. Therefore, if you define only one accessor, you cannot specify a separate accessor-access-mode for it.
- If you define two accessors, you can specify an accessor-access-mode for one of the accessors, but only if this accessor-access-mode is more restrictive than the access mode of the property.
- If you are defining an abstract property, you cannot specify the
PRIVATEaccess mode for an accessor.
For example, if the property access mode is
PUBLIC, any accessor-access-mode that you specify must bePACKAGE-PROTECTED,PROTECTED,PACKAGE-PRIVATE,orPRIVATE; if the property access mode isPROTECTED, any accessor-access-mode that you specify must bePRIVATE, unless the property is abstract. - GET [ implementation | SUPER ] .
- An accessor (
GET) that defines the property as readable. If you do not define aGETaccessor for a class property, the property cannot be read, not even from within the defining class.It is valid to omit the
GETaccessor when defining a property for an interface. It is then up to the class implementing the interface to decide whether to define theGETaccessor for the property or not. However, as stated above, if you do not define aGETaccessor for a class property, the property cannot be read. If you do not define aGETaccessor, then you must define aSETaccessor.You can define aGETaccessor using three basic forms:
If you are defining an abstract property or an interface property prototype, you cannot define theWithout an implementation GET.With the SUPERoptionGET SUPER.With an implementation GET ( [array-index-parameter] ) : get-logic END [ GET ].GETaccessor with an implementation or with theSUPERoption.Syntax for
GETaccessor without an implementation
Without an implementation, an operation that reads the property directly accesses the current value in the property's default memory.GET.If the property is an array, the default accessor implementation handles the subscript references automatically. Providing an array-index-parameter in this case is a compiler error.
Syntax for a
GETaccessor with theSUPERoptionGET SUPER.SUPERallows you to pass control to the super class. Use theSUPERoption if you want to override one of the accessors to provide extra processing or validation, but don't need to change the implementation of the other accessor. You can also useSUPERto make the access mode of the property less restrictive.Syntax for a
GETaccessor with an implementationGET ( [array-index-parameter] ) : get-logic END [ GET ] .- array-index-parameter
- Specifies an
INPUTparameter that provides access to the index value of the current element of an array property from within the get-logic. When a property is defined as an array using theEXTENToption, theGETaccessor references the single element of the property array. The array-index-parameter specifies the subscript value for the element being accessed. This is the syntax:[ INPUT ] array-index-name AS { INTEGER | INT64 }- array-index-name
- Specifies the name of the
INPUTparameter that provides the subscript value (index) for this array element. You must use this value in a subscript on the property name (property-name[array-index-name]) to access the default memory for the current array element. - INTEGER | INT64
- Specifies the data type of the index. Use the data type that supports the largest dimension that is defined for or that you expect to be fixed for the property array at run time.
Where supported, an unsubscripted array reference is a reference to the whole array. For a property array, an unsubscripted read reference invokes the GET accessor for each array element in ascending order by subscript value.
- get-logic
- Can contain ABL code that executes for any operation that
reads the property from outside its own
GETaccessor definition. This code can include any ABL statements that are valid in a method of a class, includingCATCHandFINALLYblocks. However, if you define the property itself as static, you cannot access any instance members of classes (including the defining class) or use theSUPERandTHIS-OBJECTsystem references; you can only access static class members and the local data elements of theGETaccessor. The actual value that you return from the property is entirely dependent on your get-logic code. Within get-logic, any operation that reads from property-name (such as the right-hand side of an assignment) directly reads the value of the property's default memory. However, any operation that writes to property-name within get-logic invokes the property's own SET accessor to assign the value, exactly like writing the property from outside of its own definition. If the SET accessor is defined with an implementation, that implementation determines how the value is written to the property.You do not have to use the property's default memory to provide the value read from a property. You can also use any other accessible data, such as a data member, as storage to access property values. To return a value from get-logic to any outside reader of the property, you must return a value with the correct data type using the RETURN statement (similar to any method that returns a value). If you do not invoke the
RETURNstatement in get-logic, the property returns the Unknown value (?).
- SET [ implementation | SUPER ] .
- An accessor (
SET) that defines the property as writable. If you do not define aSETaccessor, the property cannot be written, not even from within the defining class.You can define aSETaccessor using three basic forms:Without an implementation SET.With the SUPERoptionSET SUPER.With an implementation SET ( [array-index-parameter] ) : set-logic END [ SET ].It is valid to omit the
SETaccessor when defining a property for an interface. It is then up to the class implementing the interface to decide whether to define theSETaccessor for the property or not. However, as stated above, if you do not define aSETaccessor for a class property, the property cannot be written. If you do not define aSETaccessor, then you must define aGETaccessor.If you are defining an abstract property or an interface property prototype, you cannot define the
SETaccessor with an implementation.Syntax for a
SETaccessor without an implementationSET.Without an implementation, any operation that writes the property writes the value directly to the property's default memory. If the property is an array, the default accessor implementation handles the subscript references automatically.Note: This is equivalent to, but more efficient than, using an implementation to explicitly assign a value to a property.Syntax for a
SETaccessor with theSUPERoptionSET SUPER.SUPERallows you to pass control to the super class. Use theSUPERoption if you want to override one of the accessors to provide extra processing or validation, but don't need to change the implementation of the other accessor. You can also useSUPERto make the access mode of the property less restrictive.Syntax for a
SETaccessor with an implementationSET ( parameter-definition[ , array-index-parameter] ) : set-logic END [ SET ] .- parameter-definition
- Specifies an
INPUTparameter that provides access to the value written to the property from within the set-logic. The set-logic can contain ABL code that executes for any operation that writes to the property from outside its ownSETaccessor definition. This code can include any ABL statements that are valid in a method of a class, includingCATCHandFINALLYblocks. However, if you define the property itself as static, you cannot access any instance members of classes (including the defining class) or use theSUPERandTHIS-OBJECTsystem references; you can only access static class members and the local data elements of theSETaccessor. To access the value being written to the property, specify parameter-definition using the following syntax:[ INPUT ] parameter-name AS {primitive-type-name|[ CLASS ]object-type-name}- [ INPUT ] parameter-name
- Specifies the name of the INPUT parameter that you reference in set-logic to obtain the value written to the property.
- AS {primitive-type-name|[ CLASS ]object-type-name}
- Specifies the data type of the parameter as a built-in primitive type (primitive-type-name), or as a built-in or user-defined object type (object-type-name). You must specify exactly the same data type as you have defined for the property.
- array-index-parameter
- Specifies an
INPUTparameter that provides access to the index value of the current element of an array property from within the set-logic. When a property is defined as an array using theEXTENToption, theSETaccessor references a single element of the property array. The array-index-parameter specifies the subscript value for the element being accessed. This is the syntax:[ INPUT ] array-index-name AS { INTEGER | INT64 }- array-index-name
- Specifies the name of the
INPUTparameter that provides the subscript value (index) for this array element. You must use this value in a subscript on the property name (property-name[array-index-name]) to access the default memory for the current array element. - INTEGER | INT64
- Specifies the data type of the index. Use the data type that supports the largest dimension that is defined for or that you expect to be fixed for the property array at run time.
Where supported, an unsubscripted array reference is a reference to the whole array. For a property array, an unsubscripted write reference invokes the
SETaccessor for each array element in ascending order by subscript value. - set-logic
- Can contain ABL code that accesses the value written to the
property as parameter-name, then uses
parameter-name (if you choose) to set the
new value for the property. The actual value that you use to set the property is
entirely dependent on your set-logic code.
Within set-logic, any operation that writes
to property-name (such as the left-hand side
of an assignment) directly writes the specified value to the property's default
memory. However, any operation that reads from property-name within set-logic
invokes the property's own
GETaccessor to read the value, exactly like reading the property from outside of its own definition. If theGETaccessor is defined with an implementation, that implementation determines the value that is read from the property.You do not have to use the property's default memory to store the property value. You can use any other accessible data, such as a data member, as storage to store property values. If you do not write a value to property-name within set-logic, the property's default memory retains whatever value it had prior to any operation that writes to the property.
Examples
The examples that follow show two different ways to access the same private data of a class using properties.
The first example, shows a class (r-DefineProperties1) that defines a PUBLIC property (cCurrentSalesRepName) followed by a procedure that accesses this
property. The property is defined with two accessors without implementations, providing
direct access to the property value. The GET accessor is
PUBLIC, but the SET accessor is
PRIVATE, allowing only the class or an instance of the class to set the
property value. In this case, the class sets the property from data (RepName field) in the Sports2020 database provided by a buffer (bSalesRep), which is PRIVATE.
The class also provides a PUBLIC method (getNextSalesRep( )) to read the SalesRep table one record at a time and set the cCurrentSalesRepName property to the value of the RepName field for each record. This PUBLIC method also uses a
PRIVATE method (restartSalesRep( )) to
reset the record position to the beginning of the table, based on an INPUT
parameter. The class constructor also uses this PRIVATE method to
initialize the record buffer to the first record in the table. The class sets the cCurrentSalesRepName property to the Unknown value (?) if the SalesRep table is
empty or getNextSalesRep( ) reaches the end of the SalesRep table.
r-DefineProperties1.cls
|
The following procedure (r-runDefineProperties1.p) instantiates the r-DefineProperties1 class, referenced by clProps, and reads and displays the value of the clProps:cCurrentSalesRepName property in a message, starting with the first
SalesRep record found as part of class instantiation.
The procedure then displays the value of clProps:cCurrentSalesRepName in a message for each record found by the clProps:getNextSalesRep( ) method, restarting from the beginning
of the SalesRep table at the direction of the user.
r-runDefineProperties1.p
|
In the next example, the r-DefineProperties2 class defines a PUBLIC property (cNextSalesRepName) that provides the same data as the cCurrentSalesRepName property defined by the r-DefineProperties1 class. However, the GET
accessor of the cNextSalesRepName property is also used to
provide the same access to the SalesRep table that the
getNextSalesRep( ) method provides for the r-DefineProperties1 class. So, the value of cNextSalesRepName changes with each access.
r-DefineProperties2.cls
|
Because this cNextSalesRepName property
incorporates the record access provided by the getNextSalesRep( ) method, the following procedure that accesses the cNextSalesRepName property must also use the property in a
manner similar to how the r-runDefineProperties1.p
procedure uses the getNextSalesRep( ) method. As a result,
the class also provides a second, publicly writable property (lSalesRepRestart) to indicate when the reading of SalesRep records must restart from the beginning of the table. (Note that the
getNextSalesRep( ) method provides its own
INPUT parameter to indicate whether to restart record reading.)
Finally, the r-DefineProperties2 class
constructor sets lSalesRepRestart together with an initial
read of the cNextSalesRepName property in order to
initialize the record buffer to the first record of the table and pass the associated
RepName field value to the instantiating procedure as an
OUTPUT parameter.
Thus, the following procedure (r-runDefineProperties2.p) instantiates the r-DefineProperties2 class, referenced by clProps, and reads and displays the data from the clProps:cNextSalesRepName property in a manner similar to how the r-runDefineProperties1.p procedure reads and displays the same
data using the getNextSalesRep( ) method. However, because
the clProps:cNextSalesRepName property always returns the
RepName field for the next
SalesRep record in the table, the r-runDefineProperties2.p procedure must provide a separate
variable (cCurrentSalesRepName) of its own, which provides
the same function that the cCurrentSalesRepName property
provides for the r-DefineProperties1 class, which is to
maintain a current value read from the RepName field.
r-runDefineProperties2.p
|
Thus, the logic of the r-runDefineProperties2.p procedure is almost identical to the r-runDefineProperties1.p procedure, reading a clProps:cNextSalesRepName property instead of invoking a clProps:getNextSalesRep( ) method in order to read an
appropriate value from the SalesRep table.
|
For more examples of property definitions, including static and abstract properties, see the descriptions of r-CustObj.cls, r-CustObjStatic.cls, and r-CustObjAbstract.cls in the CLASS statement reference entry.
Notes
- You cannot define a property within a procedure (internal or external) or within a method of a class (constructor or destructor). It can only be defined as a member of a class or as a prototype in an interface. For more information about declaring property prototypes in an interface, see the INTERFACE statement reference entry.
PUBLIC,PACKAGE-PROTECTED,PROTECTED, andPACKAGE-PRIVATEproperties defined within a class definition (.cls) file maintain their characteristics throughout the inherited class hierarchy. Thus, you cannot override properties in a subclass that are defined in a super class.- You must define at least one
GETorSETaccessor, or define both accessors, for the property to be valid. - You never invoke the
GETandSETaccessors defined for a property directly. These methods are only invoked implicitly when you read (GET) or write (SET) the value of the property. For example, you can read or write the property by using the property in an Assignment (=) statement or by passing the property as a parameter to a method, procedure, or user-defined function. For information on reading and writing property values, see the Class-based property access reference entry. As an alternative, you can define a method in a class to read or write the value of a data member that you separately define in the same class. - If the property name is an ABL reserved keyword, you might need to use the THIS-OBJECT system reference or Type-name syntax to reference the property. For more information on referencing properties, see the reference entry for Class-based property access.
- To avoid any unexpected performance impact when using the property,
ensure that the body of any
GETorSETaccessor minimizes processing that might incur delay when referencing the property. - You cannot specify formatting information in a property definition. You
can control property formatting using the same default rules for formatting a variable or
data member:
- Rely on the default formatting for the data type of the property. For more information, see the Data types reference entry.
- Add formatting information when you access the property in a statement (for example, using a DISPLAY statement).
- You can handle application errors in an a property accessor as in any
ABL block. By executing a
RETURN ERRORaction at the block level or aTHROWaction at the block level with the presence of a ROUTINE-LEVEL ON ERROR UNDO, THROW statement, the AVM returns the ERROR condition to the statement that references the property and works much like an error raised by a method. If aRETURN ERRORalso includes the option to return a character string value, or you set the ReturnValue property of a Progess.Lang.AppError object that youTHROW, you can get this value using the RETURN-VALUE function following the statement that references the property or in aCATCHblock that catches the Progress.Lang.AppError object. If the body of an accessor contains anUNDOblock, any unhandled ERROR condition in that block undoes only the data within that block, according to theNO-UNDOsetting of the data. The property value, itself, is not undone unless the property is defined withoutNO-UNDO. For more information, see Develop Object-oriented ABL Applications. - If ERROR is raised during execution of an Assignment (=) statement, the value on the left-hand side usually
remains unchanged from its value prior to the assignment. However, if the left-hand side
of the assignment is a property and its
SETaccessor invokes theRETURN ERRORstatement (raising ERROR on the assignment), the value of the property can be changed. This is because theSETaccessor is a method, and like all methods that raise ERROR, any data elements that theSETaccessor changes retain their most recent values after ERROR is raised. Thus, if theSETaccessor changes the property value before invokingRETURN ERROR, the property retains its most recent change in value after ERROR is raised on the assignment. - If an ABL property that implements a property defined in a .NET
interface is accessed from .NET and it raises ERROR out of the accessor block, ABL returns
a .NET System.Exception to the caller. If the error is raised by executing a
RETURN ERRORwith the optional error string, the Message property of the System.Exception describes the operation where the error occurred, but the error string is available only to the ABL session, using theRETURN-VALUEfunction. If the error is raised by executing aRETURN ERRORwith an optional ABL error object or by executing anUNDO, THROW, the System.Exception Message property includes both a description of the operation where the error occurred and any messages from the ABL error object. If the error is fatal, the AVM responds as for any ABL class, generating a protrace file and exiting the session.
See also
Assignment (=) statement, Class-based property access, Data types, DEFINE VARIABLE statement, DISPLAY statement, METHOD statement, RETURN statement, VAR statement