METHOD statement

Defines a method of a class, declares a method prototype in an ABL interface, or overrides a method inherited from an ABL or .NET super class. A method is a class member that, when invoked by name, can execute code and return a value similar to a user-defined function. The description that follows begins with the general syntax for defining a method.

Note: This statement is applicable only when used in a class or interface definition (.cls) file.

Syntax

METHOD [ PRIVATE | PROTECTED | PUBLIC ][ STATIC | ABSTRACT ] 
  [ OVERRIDE ][ FINAL ] 
  { VOID |return-type}method-name 
  ( [ parameter [ , parameter ]...] ) :

  method-body

Use the following syntax to declare an interface method prototype:

METHOD [ PUBLIC ] 
  { VOID |return-type}method-name 
  ( [ parameter [ , parameter ]...] ) .

Use the following syntax to declare an abstract method prototype:

METHOD [ PROTECTED | PUBLIC ][ OVERRIDE ] ABSTRACT
  { VOID |return-type}method-name 
  ( [ parameter [ , parameter ]...] ) .
[ PRIVATE | PROTECTED | PUBLIC ]
Specifies the access mode for this method. A PRIVATE method can be called by the defining class. An instance can call the private method of another instance if they are both from the same class. A PROTECTED method can be called by the defining class and any of its derived classes. An instance can call the protected method of a second instance that is at the same level or higher in the class hierarchy. A PUBLIC method can be called by:
  • The defining class
  • Any of its derived classes
  • Any class or procedure that has access to a class instance that defines or inherits the method

Any piece of code can call a PUBLIC static method. The default access mode is PUBLIC.

When declaring an interface method prototype, the access mode for this method must be PUBLIC (the default).

When defining an abstract method, the access mode for the method cannot be PRIVATE.

If this method is defined with the OVERRIDE option, the access mode must not be more restrictive than the access mode defined for the overridden ABL or .NET super class method. ABL access modes correspond to inherited .NET access levels as follows:

  • PROTECTED matches either the .NET protected or protected internal access level
  • PUBLIC matches the .NET public access level
Note: The PRIVATE/PROTECTED/PUBLIC modifier and the STATIC/ABSTRACT modifier can appear in either order, e.g., METHOD STATIC PUBLIC VOID myMethod():... is valid syntax.
[ STATIC ]
Defines a method 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. You can call an accessible static method in any piece of code.

Without this option, ABL defines an instance method that is scoped to a single instance of the class where it is defined. You can call any public instance method (abstract or 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 call the public instance method only using an object reference to a class instance that defines the instance method as a member. If the referencing static method is defined in the same class as the public instance method, the class must instantiate itself in order to have access to an instance reference.

Note: In ABL, all PRIVATE and PROTECTED access modes are class based. An instance can access the PRIVATE member of another instance if both instances are from the same class. Likewise, a PROTECTED member can be accessed from any instance of the class or subclass that defines it. In other words, an instance can access a protected member of a second instance that is from the same level or higher in the class hierarchy..

For more information on the mechanism for calling methods of different access modes and scopes, see the reference entry for Class-based property access.

The STATIC option is not valid when you:

  • Define or implement an abstract method
  • Declare an interface method prototype
  • Implement an interface method
[ ABSTRACT ]
Defines the method 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 method, it has the following requirements:
  • You must specify the OVERRIDE option if an inherited method (abstract or otherwise) has the same name and signature.
  • You can specify either a PROTECTED or a PUBLIC access mode, depending on any inherited method you might be overriding.
  • The abstract method must be overridden and implemented in a derived class.

Any class definition for an instance method that includes the OVERRIDE option and does not include the ABSTRACT option defines a method implementation. If it also includes the ABSTRACT option, the inherited method remains or is redefined as abstract.

This option is not valid either when you define a static method or you declare an interface method prototype.

[ OVERRIDE ]
Specifies one of the following:
  • This instance method overrides the behavior of another instance method inherited from an ABL or .NET class.
  • This instance method implements, or redefines as abstract, an abstract method inherited from an ABL or .NET abstract class.
  • This instance method redefines as abstract an implemented method inherited from an ABL or .NET class.
    Note: A .NET abstract class is defined in C# with the abstract keyword.
  • This static method redefines the behavior of another static method implemented in a super class.

When you specify OVERRIDE, the method signature must match the overridden method with respect to the name, return type, and the number, types, and modes of its parameters. In addition, the access mode cannot be more restrictive than the access mode of the super class method it overrides. When overriding a .NET method, the return type and parameters must also map appropriately to the inherited .NET method return type and parameters. For more information, see the description of the return-type and parameter options.

If you are overriding an inherited abstract method and you specify the ABSTRACT option, your overriding method is also defined as abstract, and it must be implemented in a class derived from the defining class. Note that you do not have to override an inherited abstract method that you want to remain abstract as long as the inheriting class is also abstract. However, doing so allows you to specify a less restrictive access mode for the abstract method.

If you do not specify the ABSTRACT option when overriding an inherited abstract method, your method definition implements the abstract method.

If you are overriding an inherited method that already has an implementation and you specify the ABSTRACT option, your overriding method redefines the inherited method as abstract, and it must, again, be implemented in a class derived from the defining class. Note that to redefine an inherited method as abstract that already has an implementation, the defining class must also be abstract.

Note that instance methods do not override static methods and static methods do not redefine instance methods. For more information about overriding and redefining methods, see OpenEdge Development: Object-oriented Programming.

You can only override methods of a .NET super class that, in C# terms, are:

  • Declared as virtual or abstract
  • Declared as public, protected or protected internal
  • Not declared as static or sealed (FINAL)

This option is not valid when you declare an interface method prototype.

[ FINAL ]
Indicates this method cannot be overridden or redefined by a method defined in an inheriting subclass.

This option is not valid either when you define an abstract method or when you declare an interface method prototype.

VOID
Indicates this method does not return a value.
return-type
Indicates the data type of the method return value. You can specify return-type as one of the following data types. For more information on each data type, see the Data types reference entry:
{ CHARACTER | COM-HANDLE | DATE | DATETIME | DATETIME-TZ
  | DECIMAL | HANDLE | INT64 | INTEGER | LOGICAL | LONGCHAR
  | MEMPTR | RAW | RECID | ROWID |AS-data-type 
  |[ CLASS ]object-type-name }[ EXTENT [constant]]
AS-data-type
If you are defining the return type for a method that overrides a .NET super class method (abstract or otherwise) or implements a method defined in a .NET interface, return-type must specify the exact return type of the overridden or implemented .NET method. For a .NET mapped data type that is a default match for an ABL primitive type, you must use the default matching ABL data type, as shown in Table 4. (For example, INTEGER indicates 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 (the AS-data-type) that you must use to explicitly indicate the required .NET data type, as shown in Table 5. (For example, UNSIGNED-BYTE indicates a .NET System.Byte.)
Note: At run time, a method return type 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 overriding or implementing a .NET array return value, you must specify the .NET array object type (for example, "System.Int32[]" or "System.Byte[]"); you cannot use an ABL array equivalent (for example, INTEGER EXTENT or UNSIGNED-BYTE EXTENT).

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.

If you are defining the return type for a method that overrides a .NET super class method (abstract or otherwise), or that implements a method defined in a .NET interface, object-type-name must specify the exact return type of the overridden or implemented .NET method. 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 overriding or implementing a .NET array return value, you must specify the .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 a class or interface return value, ABL returns an object reference associated with the class or interface, not a class instance itself. For more information on object references, see the Class-based object reference reference entry.

[ EXTENT [constant ]]
Defines the return value as an array of data elements with a primitive or object data type. This option can specify an array return value as either determinate (has a defined number of elements) or indeterminate (has an undefined number of elements). To define a determinate array return value, specify the EXTENT option with the constant argument. This optional argument is an integer value that represents the number of elements in the array. To define an indeterminate array return value, specify the EXTENT option without the constant argument.

An indeterminate array return value can be in one of two states: fixed or unfixed, meaning it either has a fixed dimension or it does not. An indeterminate array return value has an unfixed dimension when first defined. You can fix the dimension of an indeterminate array return value by:

  • Setting the number of elements in the array return value using the EXTENT statement
  • Assigning a determinate array to the indeterminate array value, fixing it to the dimension of the determinate array
  • Passing array parameters to a procedure, user-defined function, or class-based method, so that the indeterminate array value is the target for the passing of a determinate array, fixing the indeterminate array to the dimension of the determinate array

Once fixed, ABL treats a fixed indeterminate array as a determinate array.

If you do not use the EXTENT option (or you specify constant as 0), the return value is not an array return value.

method-name
The method name. This name must be unique among all methods defined in the class hierarchy of the defining class, unless the method:
  • Includes the OVERRIDE option to override an inherited method.
  • Overloads a method in the defining class or in any super class within its inherited class hierarchy. In this case, the parameter list must differ from that of every other method with the same name in the defining class, and it must differ from that of every other method with the same name defined in every super class of the defining class.
Note: Members of a class are grouped into six namespaces, including buffers/temp-tables, methods, variables/properties/events, ProDataSets, queries, and data-sources. Methods defined as members of a class share the same namespace. There can be only one class member in this namespace with a given name. If the method is defined in a class that is derived from a .NET class, other restrictions on method-name apply. For more information, see the Notes in this reference entry.
( [ parameter [ , parameter]...] )
Defines zero or more parameters of the method.

If this method is one of several overloaded methods, the parameter list must be unique among all public and protected methods defined in the class hierarchy of the defining class. This uniqueness can be established using a different combination of number, data types, or modes for the parameters. Note that both instance and static methods overload one another within the class hierarchy.

If this method implements an interface method prototype or overrides an inherited method (using the OVERRIDE option), the parameter list must match the parameter list of the interface method prototype or a public or protected method with the same name that is inherited from a super class.

If the method implements a .NET interface method prototype or overrides an inherited .NET method (abstract or otherwise), you must explicitly map any .NET mapped types specified for parameters of the .NET method (see Table 5). Note that at run time, any explicitly mapped parameter behaves like the corresponding ABL primitive type.

For more information on the syntax of parameter, establishing uniqueness for method overloading, and on mapping .NET parameter types, see the Parameter definition syntax reference entry.

method-body
The body for a method implementation. For an interface method prototype or an abstract method, you cannot specify method-body. For more information about declaring method prototypes in an interface, see the INTERFACE statement reference entry.

Define method-body using the following syntax:

method-logic 
       .
       .
       .
    [catch-block[catch-block...]]
    [finally-block]
END [ METHOD ] .
method-logic
The logic of the method. This logic can contain the ABL statements that are allowed within a procedure block, including class-related statements.

If you define the method to return a value of the data type specified by return-type, you can execute the RETURN statement to set a value of that data type to return at run time. If return-type is defined as a .NET array of mapped types (for example, "System.Byte[]"), you must return an object reference of the specified .NET array of mapped types in the RETURN statement. You cannot return an ABL array of a type that maps to the .NET array type (for example, INTEGER EXTENT) or the AVM raises a run-time error. If you do not execute any RETURN statement for return-type in the method-logic, the method returns the Unknown value (?) as its return value.

If you are defining an instance method with the OVERRIDE option, you can also call the overridden implementation of this method in the class hierarchy using the SUPER system reference. You can also optionally call any instance method defined in the same class using the THIS-OBJECT system reference.

If you are defining a static method, you cannot access any instance members of a class (including the defining class) nor can you use the SUPER and THIS-OBJECT system references. From a static method, you can access only other static members of a class and the local variables or other local data elements of the method.

Each logic statement must end with a period.

catch-block
Specifies a CATCH statement that defines error handling code for one or more error types. A DO block does not have any default error handling. Therefore, a DO block must have error handling options specified such that it becomes an undo-able block. Otherwise, ABL generates a compiler warning. For more information on catch-block, see the CATCH statement reference entry.
finally-block
Specifies a FINALLY statement that defines the processing that must occur after all other processing in the block occurs. For more information on finally-block, see the FINALLY statement reference entry.
END [ METHOD ]
Specifies the end of the method body definition. You must end the method body definition with the END statement.

Examples

The following example shows the definition of an instance method in a class (which might implement a method prototype declared in an interface, as depicted in the second example):

METHOD PUBLIC CHARACTER GetCustomerName (INPUT inCustNum AS INTEGER):

  FIND ttCust WHERE ttCust.CustNum = inCustNum NO-ERROR.
  IF AVAILABLE ttCust THEN
    RETURN ttCust.CustName.
  ELSE
    RETURN ?.

END METHOD.

The following example shows the definition of a method prototype declaration in an interface (which can be implemented by an instance method definition in a class, as depicted in the first example):

INTERFACE acme.myObjs.Interfaces.ICustObj:

  METHOD PUBLIC CHARACTER GetCustomerName (INPUT inCustNum AS INTEGER).

END INTERFACE.

For more examples of method definitions, including static and abstract methods, see the descriptions of r-CustObj.cls, r-CustObjStatic.cls, and r-CustObjAbstract.cls in the CLASS statement reference entry.

Notes

See also

Class-based method call, CLASS statement, FUNCTION statement, INTERFACE statement, Parameter definition syntax, PROCEDURE statement, RETURN statement, Type-name syntax, USING statement