Generics concepts and terminology in object-oriented ABL
- Last Updated: May 3, 2024
- 4 minute read
- OpenEdge
- Version 13.0
- Documentation
Generics allow you to create classes and interfaces that work with different data
types. In object-oriented ABL, generic types are used in support of built-in
collections classes and interfaces (Progress.Collections.*). You can also define your own user-defined
generics.
Generic types allow for code reuse and strong compile-time type compatibility checking. With generics, you can define and use type-safe containers, allowing you to catch more problems at compile-time instead of at runtime.
This topic describes some of the terminology and concepts of ABL generic types. For information on .NET generic types, see Reference .NET generic types in Use .NET Classes in ABL Applications.
Terminology
The following diagram shows some terminology used to describe the different syntax components of generics in ABL. The first statement shows how to define a user-defined generic type and the second shows how to define a variable that uses that 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.
Type parameters are specified in class and interface definitions and method declarations inside the generic type.
The type constraint indicates what types are allowed by the client code when instantiating a generic type.
Type arguments are the types supplied by the client of the generic type.
A constructed generic type specifies a particular set of data types for its type parameters.
The following sections go into more detail on these concepts and terminology.
Generic type
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 a constructed generic 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 generic 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 generic 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).