Override .NET methods
- Last Updated: October 21, 2022
- 5 minute read
- OpenEdge
- Version 13.0
- Documentation
In ABL, you can override any ABL method inherited by an ABL class using the
OVERRIDE option of the METHOD statement.
You use a similar ABL mechanism to override a .NET method. However in .NET, you can only
override inherited methods that are defined to be overridable. Similarly in ABL, you can
only override an inherited .NET method that has been defined (in C#) as virtual or abstract.
override keyword
instead of the virtual or abstract keyword.
This simply means that the .NET method is itself an override
of a virtual or abstract super
class method higher up in the class hierarchy.In addition, the method must be defined with one of the following .NET access level modifiers, which correspond to access modes in ABL:
-
public -
protected -
protectedinternal
The overriding ABL method must have an ABL access mode that is equivalent to or less restrictive than the access level of the overridden .NET method. So, the ABL method access mode can correspond to the .NET access level modifier as follows:
- You can only override a
public.NET method with aPUBLICABL method. - You can override a
protectedor aprotected internal.NET method with either aPROTECTEDor aPUBLICABL method.
You cannot override a .NET method defined as any of the following:
-
static -
sealed(FINAL) -
DestroyHandle( )method -
Dispose( )method -
Finalize( )method -
GetHashCode( )method
The listed methods are all defined as overridable in .NET. However, ABL
defines these methods as FINAL for an ABL session.
Finalize() and Dispose() are not overridable because
they may be called on a separate thread which handles .NET garbage collection. The
single-threaded AVM is unable to execute ABL code on the garbage collection thread.
DestroyHandle() and GetHashCode() may not be overridden
because the AVM part of the object being called may no longer exist when the AVM attempts to
execute the override.
WndProc( ) method,
doing so can be risky. The method will be called for every event,
like WM_MOUSEMOVE and WM_PAINT,
so it can be called thousands of times for a single form, causing
performance issues. It can also be called at unexpected times and
cause unexpected behavior. Overriding WndProc( ) when
using ABL embedded windows with .NET forms can be especially problematic.
For more information, see Use .NET forms with ABL windows.As with overriding an inherited ABL method, the name, return type, and the signature of the overriding ABL method must match the overridden .NET method with respect to the number of parameters, the corresponding parameter modes, and the corresponding data types. For information on identifying .NET parameter modes, see Specify .NET constructor and method parameters.
You can also define the overriding ABL method
with or without the ABSTRACT option, whether or
not the overridden .NET method is abstract. Note that to use
the ABSTRACT option the inheriting ABL class must
also be abstract. However, as for an inherited ABL abstract method,
the first non-abstract ABL subclass that inherits a .NET abstract
method must implement the inherited .NET abstract method unless
an abstract ABL subclass implements the method higher in the class
hierarchy.
As described previously, when you call an overloaded .NET method,
you must explicitly indicate the .NET parameter data types
that correspond to the particular method overloading you want to
call (see Pass ABL data types to .NET constructor and method parameters). When overriding a .NET method,
you must follow similar rules for how to define the parameters and
return type in ABL based on how the parameters are defined in .NET.
If the data type of a method element is a .NET mapped data
type, and this mapped type is the default match for a given
ABL primitive data type, you must specify the corresponding ABL
primitive data type. However, if a .NET mapped type is not the
default match of any ABL primitive data type, you must specify the
data type using an AS data type keyword that represents
the required .NET mapped type. See Table 1 for information on
both the .NET mapped types you must specify as default mappings
and those you must specify using a corresponding AS data type.
For example, this is the C# declaration for a .NET method you can override:
|
This is the ABL method prototype required to override this .NET method:
|
Note that at run time, ABL interprets these
parameter and return values as the corresponding ABL data types
that map to their .NET equivalents. So, for example, ABL interprets piArg as
an INTEGER and the return type as a DECIMAL value.
So, to call this method in ABL, you might use the following code,
where derivedInstance is a reference to an ABL
class instance that defines the ABL override of Calculate( ):
|
To override .NET methods that pass and return .NET object types, including .NET array types, you must define the parameters and return types using the equivalent .NET object types.
For example, this is the declaration for a .NET method you can override:
|
You might override this BeginReceiveFrom( ) method
in ABL as follows:
|
BeginReceiveFrom( ) method with a similar prototype that
is not declared as virtual. Its prototype is borrowed and
modified here in order to illustrate overriding.Note that most of the .NET object type
names for the BeginReceiveFrom( ) method
override transfer exactly. However, the C# primitive array type, byte[], maps
to the .NET array object type with the type name, "System.Byte[]".
You also cannot specify this .NET array type in ABL
using the corresponding AS data type, such as in
this case UNSIGNED-BYTE EXTENT.
The C# primitive type, int, maps to the .NET System.Int32.
However, because the default match for the ABL primitive type, INTEGER,
is System.Int32, you simply use INTEGER to
define the parameters with that .NET type. Finally, the .NET ref directive
declares a parameter access level that corresponds to the ABL access
mode, INPUT-OUTPUT. (In this example, the remaining
parameter definitions also have the optional INPUT access
mode specified for readability.)
The following table summarizes the rules for defining each .NET method parameter and return type for an ABL method that overrides a .NET method.
| To define this .NET element . . . | Follow this rule . . . |
|---|---|
| .NET mapped data type | Use either the default-matched ABL data type
or the AS data type that maps to the corresponding .NET type,
as specified in Table 1. |
| .NET object type that is not mapped | Use the corresponding .NET object type. For .NET arrays, you cannot
use the ABL EXTENT option—you must specify the equivalent .NET
array object type surrounded in quotes (for example, use
"System.Byte[]" or "System.Drawing.Point[]",
not
UNSIGNED-BYTE EXTENT or
System.Drawing.Point EXTENT). However, if the
corresponding .NET array is specified as a System.Array object, you
must also use System.Array. |
| .NET parameter mode | Use the corresponding ABL parameter mode specified in Table 1. |
1 - You apply these same rules to define properties and the parameters and return types of methods that you implement in a .NET interface. For more information, see Implement .NET interfaces in ABL.