Interfaces in AL
Understanding Implementation vs Usage
Interfaces in AL were introduced in Business Central 2020 release wave 1 and provide a formal way to define behavioural contracts without tying code to a specific implementation. They allow developers to describe what capabilities are required, while leaving how those capabilities are implemented open and replaceable.
This approach reduces dependency on concrete implementations, improves reusability, and enables polymorphic behaviour, where the same call can execute different logic depending on which implementation is used. Interfaces are a core building block for designing flexible, extensible, and maintainable Business Central solutions.
What Is an Interface in AL?
An interface in AL defines a set of procedure signatures that implementing objects must provide. The interface itself contains no executable code. Instead, codeunits or enums implement the interface and supply the actual logic.
The AL compiler enforces the contract strictly. Any object that claims to implement an interface must implement all procedures exactly as defined, otherwise compilation fails.
An interface:
•Defines required capabilities
•Contains only procedure declarations
•Cannot be executed directly
•Must be implemented by other objects
An interface does not:
•Contain business logic
•Access tables
•Define UI behavior
How Interfaces Are Used Conceptually
Interfaces allow you to write code that depends on what an object can do, not which object it is. Variables can be declared as an interface type, and any implementation that fulfils the interface contract can be passed at runtime.
This enables:
•Substitution of business logic
•Removal of conditional branching
•Cleaner extensibility models
•Easier testing and replacement of logic
Interface Declaration (Code Example)
The following example defines an interface that represents an address provider.
interface "IAddressProvider"
{
procedure GetAddress(): Text
}
This interface declares a single responsibility: returning an address.
Implementing the Interface Using Codeunits
Multiple codeunits can implement the same interface, each providing a different behavior.
Company Address Implementation
codeunit 50200 CompanyAddressProvider implements IAddressProvider
{
procedure GetAddress(): Text
var
ExampleAddressLbl: Label 'Company address \ Denmark 2800';
begin
exit(ExampleAddressLbl);
end;
}
Private Address Implementation
codeunit 50201 PrivateAddressProvider implements IAddressProvider
{
procedure GetAddress(): Text
var
ExampleAddressLbl: Label 'My Home address \ Denmark 2800';
begin
exit(ExampleAddressLbl);
end;
}
Each codeunit fulfills the same contract but returns a different result.
Using Enums to Resolve Interface Implementations
Enums can implement interfaces and act as implementation selectors. This allows runtime resolution of which implementation should be used.
Example: Enum with Interface
enum 50200 SendTo implements IAddressProvider
{
Extensible = true;
value(0; Company)
{
Implementation = IAddressProvider = CompanyAddressProvider;
}
value(1; Private)
{
Implementation = IAddressProvider = PrivateAddressProvider;
}
}
This pattern is commonly used to map business choices to technical behavior.
Calling the Interface from a Page
The page below demonstrates how an interface is resolved and executed at runtime.
Example: Calling Interface from Page
page 50200 MyAddressPage
{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
layout
{
area(Content)
{
group(MyGroup)
{
}
}
}
actions
{
area(Processing)
{
action(GetAddress)
{
ApplicationArea = All;
trigger OnAction()
var
AddressProvider: Interface IAddressProvider;
begin
AddressproviderFactory(AddressProvider);
Message(AddressProvider.GetAddress());
end;
}
action(SendToHome)
{
ApplicationArea = All;
trigger OnAction()
begin
sendTo := sendTo::Private;
end;
}
action(SendToWork)
{
ApplicationArea = All;
trigger OnAction()
begin
sendTo := sendTo::Company;
end;
}
}
}
local procedure AddressproviderFactory(var iAddressProvider: Interface IAddressProvider)
begin
iAddressProvider := sendTo;
end;
var
sendTo: enum SendTo;
}
Here, the page does not know which address provider is used. It only relies on the interface.
Extending Interfaces
Starting from Business Central 2024 release wave 2, interfaces themselves can be extended. This allows additional behavior to be introduced without breaking existing implementations.
Interfaces should always be designed with extensibility in mind, especially when published or reused across extensions.
Design Guidelines for InterfacesWhen designing interfaces:
•Use clear, meaningful names
•Keep responsibilities small and focused
•Avoid adding methods after publication
•Document expected behavior
•Avoid circular dependencies
AL analyzers enforce many of these rules to prevent breaking changes.
Lists and Dictionaries of Interfaces
(Business Central 2025 release wave 1 and later)
From runtime v26, interfaces can be stored in List and Dictionary data types, enabling advanced runtime behavior.
Dictionary of Interfaces Example
codeunit 50120 MyDictionaryCodeunit
{
procedure MyProcedure(): Dictionary of [Integer, Interface "Barcode Font Provider"]
var
localDict: Dictionary of [Integer, Interface "Barcode Font Provider"];
IProvider: Interface "Barcode Font Provider";
begin
localDict.Add(2, IProvider);
exit(localDict);
end;
}
List of Interfaces Example
interface IShape
{
procedure GetArea(): Decimal;
}
codeunit 50101 Circle implements IShape
{
procedure GetArea(): Decimal
var
Radius: Decimal;
begin
Radius := 5;
exit(3.14 * Radius * Radius);
end;
}
codeunit 50102 Square implements IShape
{
procedure GetArea(): Decimal
var
SideLength: Decimal;
begin
SideLength := 4;
exit(SideLength * SideLength);
end;
}
codeunit 50103 ShapeListDemo
{
trigger OnRun()
var
ShapeList: List of [Interface IShape];
Shape: Interface IShape;
CircleShape: Codeunit Circle;
SquareShape: Codeunit Square;
begin
ShapeList.Add(CircleShape);
ShapeList.Add(SquareShape);
foreach Shape in ShapeList do
Message('The area of the shape is: %1', Shape.GetArea());
end;
}
This demonstrates true polymorphism in AL.
Summary
Interfaces in AL provide a powerful and controlled way to decouple logic from implementation. They enable replaceable behavior, cleaner architecture, and long-term extensibility without invasive changes.
A well-designed interface:
•Represents a single responsibility
•Enables substitution without modification
•Is stable once published
•Forms the backbone of advanced extensibility patterns
Understanding interfaces is essential before working with event-driven architectures and advanced extensibility in Business Central.
Hot Topics in Business Central