Try OpenEdge Now
skip to main content
Object-oriented Programming
Getting Started with Classes, Interfaces, and Objects : Using the CLASS construct : Defining data members within a class
 

Defining data members within a class

Data members define instance data of a class. They must be defined in the main block of the class. You can define variables, buffers, temp-tables, queries, ProDataSets, and data-sources as data members of a class, with restrictions as noted below. You can also define certain types of data as properties. For more information, see Defining properties within a class.
Data members of a class are defined using the standard ABL DEFINE statements, with the addition of an optional access mode for each data member. The access mode is valid only for data member definitions in the main block of a class definition file (not for local method data, for example). Temp-tables and ProDataSets must be defined as data members of the class. They cannot be defined within a method of a class. This restriction is equivalent to external procedures, where temp-tables and ProDataSets cannot be defined within internal procedures or user-defined functions.
This is the syntax for defining a variable data member.

Syntax

DEFINE [ PRIVATE | PROTECTED | PUBLIC ][ STATIC ]
[ SERIALIZABLE | NON-SERIALIZABLE ]{ VARIABLE }  
data-member-name data-member-definition .
This is the syntax for defining handle-based data members, which cannot be defined as PUBLIC:
DEFINE [ PRIVATE | PROTECTED ][ STATIC ]
[ SERIALIZABLE | NON-SERIALIZABLE ]
  { BUFFER | TEMP-TABLE | QUERY | DATASET | DATA-SOURCE }  
data-member-name data-member-definition .
Element descriptions for these data member syntax diagrams follow:
[ PRIVATE | PROTECTED | PUBLIC ]
The access mode for the data member. The default access mode is PRIVATE. Private data members or properties are accessible from within the class where they are defined. Protected data members are accessible from within the class where they are defined and in any subclass of the defining class. Public data members are accessible both within the class hierarchy and from outside the class hierarchy where they are defined. Note that the only kind of data member that can have a public access mode is a variable data member. For more information on accessing data members, see Accessing data members and properties.
Note: An instance can access a private variable of another instance if they are both instances of the same class. An instance can access a protected variable of a second instance of a class that is at the same level or higher in the class hierarchy. This behavior is valid for variables, but not temp-tables or ProDataSets.
Only data members in the CLASS block can have an access mode. Local variables defined within methods cannot have an access mode and are accessible only from within the method, similar to the way local variables defined within an internal procedure are accessible only within the defining internal procedure.
[ STATIC ]
Specifies the scope of the data member. By default, data members of a class are instance data members, meaning that one copy of a given data member is created and scoped to each instance of the class in which it is defined. However, data members can also be defined as static by specifying this keyword. ABL creates only one copy of a static data member on first reference to the class type in which it is defined, scopes that data member to the class type, and makes it available through that class type throughout the ABL session without the need for a class instance. Unless specified otherwise, any reference to a data member in this manual is assumed to be a reference to an instance data member.
For more information on static data members, see Using static members of a class.
Note: A static data member, which is scoped to a class type, is distinct from a static widget or other static handle-based object. A static handle-based object, such as a menu, temp-table, or ProDataSet, is a compile-time defined and bound object that can also be implemented as an equivalent dynamic handle-based object, which can be created and bound at run time only. Thus, you can define a static handle-based object, such as a temp-table, that is also a static data member, and you can define a HANDLE variable as a static data member, which can, in turn, reference a dynamic or static handle-based object. Typically, the usage of the term, static, can be understood from the context. Otherwise, OpenEdge documentation attempts to clarify the meaning in any ambiguous context.
[ SERIALIZABLE | NON-SERIALIZABLE ]
Class-based objects that are defined as serializable (using the SERIALIZABLE option in the CLASS statement) can be passed as parameters in remotes call between the AppServer and ABL clients and can be serialized to binary or JSON format. By default, both passing an object as a parameter and serializing an object to binary via the Progress.IO.BinarySerializer class include all data members regardless of access mode. However, for JSON serialization via Progress.IO.JsonSerializer, only public data members are serialized. To include a protected or private variable, temp-table, or ProDataSet during JSON serialization, SERIALIZABLE must be added to the definition. See the Serialize( ) method (JSON) entry in OpenEdge Development: ABL Reference for more information.
Use the NON-SERIALIZABLE option to exclude a given variable from parameter passing between an AppServer and ABL client or from the serialization process via the Progress.IO.BinarySerializer or Progress.IO.JsonSerializer class. A variable marked as NON-SERIALIZABLE is assigned its initial value when the object is deserialized.
Note: The SERIALIZABLE option can only be used with variables, temp-tables, and ProDataSets. Using it with buffers, queries, or data sources will raise a compiler error.
data-member-name
The name of the variable, buffer, temp-table, query, ProDataSet, or data-source. This data-member-name must be unique within the class hierarchy according to its particular class member namespace. For example, a variable data member must be unique within a namespace that includes the names of properties, variable data members, and class events. For more information, see Namespaces for naming class members.
Variable data members defined within a class can be named the same as an ABL reserved keyword. In all contexts, a variable data member whose name is a reserved keyword must be qualified when referenced, either by an object reference (which can be THIS-OBJECT) or if it is static, with a static type name. For more information on accessing data members, see Accessing data members and properties. For more information on using static type-name syntax to reference static variable data members, see Accessing static members.
data-member-definition
The remaining syntax available for defining the variable, buffer, temp-table, query, ProDataSet, or data-source.
Note that some of these data members are complex data members. A complex data member is a data member, such as a ProDataSet, that must be defined together with one or more component data members. In general, the component data members of an associated complex data member must be defined with an equal or less restrictive access mode than the associated complex data member. For example, if you define a PRIVATE ProDataSet, the temp-tables and buffers of the ProDataSet can be defined with the PROTECTED access mode. Also, the component data members of a complex static data member definition can consist only of other static data members that are defined with a compatible access mode in the current class hierarchy. However, the component data members of a complex instance data member can consist of both instance and static data members.
For example, adding four data members to the sample class definition results in this code:
USING acme.myObjs.*.
USING acme.myObjs.Common.*.

CLASS acme.myObjs.CustObj INHERITS CommonObj:
  DEFINE PUBLIC VARIABLE iNumCusts AS INTEGER NO-UNDO.

  DEFINE PROTECTED TEMP-TABLE ttCustomer NO-UNDO
    FIELD RecNum AS INTEGER
    FIELD CustNum LIKE Customer.CustNum
    FIELD Name LIKE Customer.Name
    FIELD State AS CHARACTER.

  DEFINE PRIVATE VARIABLE rMsg       AS CLASS MsgObj    NO-UNDO.
  DEFINE PRIVATE VARIABLE rCreditObj AS CLASS CreditObj NO-UNDO.  
...
END CLASS.
For PUBLIC and PROTECTED definitions the data member name is available to the class that defines it and to all subclasses of this class. The definition of a PUBLIC or PROTECTED data member does not need to be repeated in the subclass or the referencing class. The use of the data member name in a subclass refers to the data member defined in the subclass or to data members defined in a super class within its class hierarchy. There is no separate copy of the data member when it is referenced from a subclass. If a subclass references a data member from a super class, the compiler accesses the data member definition in the super class to identify its type information. If the data member definition is repeated in the subclass, this results in a compiler error.
When a PUBLIC instance data member is accessed outside of its class hierarchy, it is accessed through an object reference, using the object-reference:data-member-name syntax. The data member is defined in the referenced class and no separate copy is made in the referencing class. That is, the referencing class does not repeat the definition for a data member that it references in another object. A data member definition of the same name in the referencing class is treated as an entirely separate data member from the one in the referenced class.
For example, assuming the previous class definition for acme.myObjs.CustObj suppose we define a new class acme.myObjs.NECustObj that inherits and references the data members of its super class acme.myObjs.CustObj. If the class CustObj defines behavior for handling Customer data in the application, the new subclass NECustObj can be thought of as a specialization of that class that defines additional or overridden behavior just for Customer records for the New England area.
In the following variation of a sample class, NECustObj, notice that both the PUBLIC and PROTECTED data members, iNumCusts and ttCustomer, are inherited from CustObj and accessible within its definition:
USING acme.myObjs.*.

CLASS acme.myObjs.NECustObj INHERITS CustObj:

  METHOD PRIVATE VOID DisplayCust ( ):
    iNumCusts = iNumCusts + 1.
    FOR EACH ttCustomer:
      DISPLAY ttCustomer.
    END.
  END METHOD.

END CLASS.
The following is another class, MyMain, that uses the NEW statement to create an instance of the acme.myObjs.NECustObj class and assign its object reference to the variable rNECust. In this case, only the PUBLIC data member iNumCusts of NECustObj is accessible to this class:
USING acme.myObjs.*.

CLASS MyMain:

  DEFINE PRIVATE VARIABLE rNECust AS CLASS NECustObj NO-UNDO.

  METHOD PRIVATE VOID DisplayCust ( ):
rNECust = NEW NECustObj( ).
    rNECust:iNumCusts = rNECust:iNumCusts + 1.
    /* Can not access PROTECTED ttCustomer */
  END METHOD.

END CLASS.
* Comparison with procedure-based programming