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.
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:
Use the following syntax to declare an abstract method prototype:
METHOD [ PROTECTED | PUBLIC ][ OVERRIDE ] ABSTRACT { VOID |return-type}method-name ( [ parameter [ , parameter ]...] ) . |
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:
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.
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:
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.
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:
This option is not valid when you declare an interface method prototype.
This option is not valid either when you define an abstract method or when you declare an interface method prototype.
{ 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]] |
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).
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).
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.
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:
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.
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.
Define method-body using the following syntax:
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.
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.
In .NET, these methods are overridable. However, OpenEdge defines these methods as FINAL for an ABL session. Instead of overriding .NET methods (such as Dispose( )) that destroy or otherwise clean-up .NET resources, always use a destructor in the ABL class to manage class clean-up using these methods, even when inheriting from a .NET class. Similarly, if you want to return an ABL-processed value generated by GetHashCode( ), create a separate ABL method that calls GetHashCode( ) to return the value.