Interfaces in Business Central AL: Complete Beginner Guide
Learn how interfaces work in Microsoft Dynamics 365 Business Central AL and how they help you separate contracts from implementations, reduce dependencies and build flexible business logic.
What is an interface?
An interface defines a contract: it describes which procedures an implementation must provide, without defining the implementation itself. A codeunit can implement an interface and provide the actual business logic.
Why use interfaces in Business Central?
- Separate business contracts from implementation details.
- Allow multiple implementations of the same behavior.
- Make code easier to replace and extend.
- Reduce direct dependencies between business logic components.
- Support polymorphism and cleaner automated testing.
Basic interface syntax
interface "Payment Provider"
{
procedure ProcessPayment(Amount: Decimal): Boolean;
}The interface declares a procedure. It does not contain the implementation of that procedure.
Implementing an interface in a codeunit
codeunit 50130 "Card Payment Provider" implements "Payment Provider"
{
procedure ProcessPayment(Amount: Decimal): Boolean
begin
// Card payment logic
exit(true);
end;
}The implementing codeunit must provide the procedures declared by the interface.
Multiple implementations
The real advantage becomes clear when several components implement the same contract.
codeunit 50131 "Cash Payment Provider" implements "Payment Provider"
{
procedure ProcessPayment(Amount: Decimal): Boolean
begin
// Cash payment logic
exit(true);
end;
}
codeunit 50132 "Card Payment Provider" implements "Payment Provider"
{
procedure ProcessPayment(Amount: Decimal): Boolean
begin
// Card payment logic
exit(true);
end;
}Both codeunits expose the same operation through the interface while keeping their implementation details separate.
Using an interface variable
An interface variable can reference an implementing object. This lets business logic work with the contract instead of depending directly on one implementation.
var
PaymentProvider: Interface "Payment Provider";
PaymentResult: Boolean;
begin
PaymentProvider := "Card Payment Provider";
PaymentResult := PaymentProvider.ProcessPayment(1500);
end;The important design benefit is that the calling code can depend on the interface rather than a concrete implementation.
Interface with an Enum
A common practical pattern is to use an enum to select an implementation. The enum represents the business choice while the interface represents the behavior.
enum 50130 "Payment Method"
{
Extensible = true;
value(0; Cash) { }
value(1; Card) { }
}
A factory-style codeunit can then map the selected method to the appropriate implementation. This keeps selection logic separate from payment processing logic.
Polymorphism in AL
Polymorphism means that the same interface call can execute different implementations. For example, calling ProcessPayment through the interface can execute card, cash or another future payment provider implementation.
procedure ExecutePayment(PaymentProvider: Interface "Payment Provider"; Amount: Decimal): Boolean
begin
exit(PaymentProvider.ProcessPayment(Amount));
end;This procedure does not need to know which concrete provider is being used.
The is operator
The is operator can be used when you need to determine whether a value is compatible with a particular interface or type.
if PaymentProvider is "Payment Provider" then
Message('A payment provider is available.');Use type checks only when they are genuinely needed. In many designs, simply programming against the interface is cleaner.
The as operator
The as operator can be used for type casting when a compatible value needs to be treated as another type.
SomeInterface := SomeValue as "Payment Provider";Extending an interface
AL supports extending interfaces. An extended interface can add additional procedures while preserving the original contract for existing implementations where appropriate. Check the target Business Central version because interface language features can evolve between platform versions.
interface "Advanced Payment Provider" extends "Payment Provider"
{
procedure RefundPayment(Amount: Decimal): Boolean;
}
Real-world example: shipping providers
Interfaces are useful when a Business Central solution may integrate with multiple shipping providers.
interface "Shipping Provider"
{
procedure CreateShipment(DocumentNo: Code[20]): Text;
procedure CancelShipment(ShipmentId: Text): Boolean;
}Separate codeunits could implement the contract for DHL, FedEx, UPS or an internal logistics service. The sales or warehouse business logic can work with the interface instead of hard-coding one provider.
Interfaces and dependency reduction
Without an interface, a business process may directly depend on a specific codeunit. Replacing that implementation can then require changes in several places. With an interface, the process can depend on the contract and the implementation can change independently.
Business Process
|
v
Shipping Provider Interface
|
+---+---+
| | |
DHL UPS Custom
Interfaces and automated testing
Interfaces can make testing easier because business logic can be designed around a contract rather than a concrete external service. A test-oriented implementation can provide controlled behavior while the production implementation calls the real service.
Common mistakes
- Creating an interface when a simple procedure or codeunit is enough.
- Putting implementation logic into the wrong layer.
- Creating very large interfaces with unrelated responsibilities.
- Using excessive type checks instead of relying on polymorphism.
- Hard-coding a concrete implementation everywhere instead of using the interface.
- Ignoring version compatibility when using newer interface language features.
Best practices
- Keep interfaces focused on one responsibility.
- Use meaningful business-oriented names for interfaces and procedures.
- Depend on interfaces where multiple implementations are expected.
- Keep external integration details inside the implementing codeunit.
- Combine interfaces with enums when a business process has selectable strategies.
- Avoid unnecessary casts and runtime type checks.
- Document important contracts and assumptions.
- Test the business process independently from external implementations where practical.
Interface vs codeunit
| Interface | Codeunit |
|---|---|
| Defines a contract | Contains executable business logic |
| Can have multiple implementations | Provides a concrete implementation |
| Helps abstraction and polymorphism | Executes procedures and logic |
Frequently asked questions
Can one codeunit implement an interface?
Yes. A codeunit can implement an interface by declaring the interface in its declaration and providing the required procedures.
Can multiple codeunits implement the same interface?
Yes. This is one of the main reasons to use interfaces: multiple implementations can follow the same contract.
Should every codeunit use an interface?
No. Interfaces are most useful when you need abstraction, multiple implementations, replaceable strategies or reduced coupling.
Are interfaces useful for Business Central integrations?
Yes. They can separate integration contracts from provider-specific HTTP, authentication or mapping logic.