Generics concepts and terminology in object-oriented ABL
- Last Updated: January 22, 2026
- 3 minute read
- OpenEdge
- Version 12.8
- Documentation
In object-oriented ABL, generic types are used in support of built-in
collections classes and interfaces (Progress.Collections.*). Generic types allow for code reuse and strong
compile-time type compatibility checking. This topic describes some of the concepts
and terminology of ABL generic types. For information on .NET generic types, see
Reference .NET generic types in Use
.NET Classes in ABL Applications.
Generic type
A generic type is an object-oriented type (class or interface) that accepts one or more type parameters, allowing the class to defer the specification of such parameters until the class is declared and instantiated by a client (user) of the class. This allows the implementation to be re-used by many diverse types, instead of having to create a class for each distinct type, and without the cost of having to cast references at runtime.
With generics, you can define and use type-safe collections, allowing you to catch more problems at compile-time instead of at runtime.
A generic type is denoted by a type name enclosed in angle brackets. For example,
<T>. The "T" is a placeholder for the real type you use when
you declare and create the class. By convention, a single letter is used, and more
specifically "T" is used, unless multiple parameters are required for a particular
class.
- Variable declarations
- Method declarations and invocations
NEWfunction
Type arguments in variable declarations
When you create a Progress.Collections.List<T>, you must specify the type of
objects allowed in the list. You do this by supplying a type
argument. A type argument is the type
supplied by the client (user) of the generic type. When using a generic type, you
must specify the same number of type arguments as there are type parameters defined
in the generic type. You cannot instantiate a generic type without specifying type
arguments.
List<T>:
|
Ant and Person. This
allows the client code to have List<Ant>
(referred to as "List of Ant") and List<Person> (referred to as "List of Person").Referencing a generic type like this is referred to as "constructing the type". Therefore, a reference to a generic type that specifies a particular set of data types for its type parameters is referred to as a "reference to its constructed type name".
The compiler requires that each type argument has an "is-a" relationship to
the corresponding type parameter. In other words, the argument must either be,
inherit from, or implement the type parameter. Because the List<T> type defines a type parameter of type Progress.Lang.Object, List<T> can be passed in any type of object-oriented ABL or .NET
object as a type argument, but not any scalar types.
After you declare a variable using the constructed type name, the compiler ensures that the type of the type arguments are used whenever the generic class uses the type parameter.
Method declarations and invocations
Add() and Get()
methods of the Progress.Collections.List<T>
class:
|
Add()
method requires a Person for a List<Person> and the Get() method returns a Person.
|
List<Person> to List<Ant>, then both the Add() and
Get() calls would not compile because the
Person and Ant
types are not compatible.Type compatibility rules
List<T>
implements IList<T>, and the type arguments
match exactly (Ant):
|
Ant has Insect in its hierarchy, whether as a super class or an
interface, the following ABL statement is not allowed, because the type argument
does not match exactly:
|
CAST or DYNAMIC-CAST).