Business Central AL Interface type

The AL Interface Type

Unfortunately I’m not able to attend NAVTech Days this year, but I am paying attention from a far and saw some very interesting posts on Twitter about a new type available in the forthcoming Business Central 16.x release. The AL interface type.

The concept of interfaces won’t be new to any one from the object orientated world of programming languages. I first used them with Java and it’s great to see Microsoft expanding the AL language to give us more features that open up a whole new world of software design.

The AL interface type give us the ability to use the techniques of abstraction and loose coupling in AL. To explain this lets look at an interface declaration:

interface IErrorHandler
{
    procedure HandleError(ErrorCode : Code[10]; ErrorMessage : Text[1024]);
}

As we can see, the interface IErrorHandler declares a procedure but does not have a procedure body. The procedure is not implemented in the interface.

A codeunit must be created to implement the interface and provide the behaviour. Implementing codeunits must implement every procedure declared by any interface it implements. An important point to remember when designing interfaces.

To implement an interface, we use the implements keyword followed by the interface name after the codeunit declaration:

codeunit 50104 "Throw Error" implements IErrorHandler
{
    procedure HandleError(ErrorCode: Code[10]; ErrorMessage: Text[1024])
    var
        Errortext: Label 'Error Code: %1\Error Message: %2';
    begin
        Error(ErrorText, ErrorCode, ErrorMessage);
    end;
}

An interface can be implemented by many different codeunits, all providing their own behaviour. Lets create another implementation of IErrorHandler:

codeunit 50105 "Log Errors in Database" implements IErrorHandler
{
    procedure HandleError(ErrorCode: Code[10]; ErrorMessage: Text[1024])
    var
        ErrorLog : Record "Error Log";
    begin
        ErrorLog.Validate(Code, ErrorCode);
        ErrorLog.Validate(Description, ErrorMessage);
        ErrorLog.Validate("Logged On", CurrentDateTime);
        ErrorLog.Insert();
    end;
}

So now we have two codeunits which both implement IErrorHandler in their own way. The compiler knows that any codeunit that implements IErrorHandler must implement the HandleError function, which means we can write generic, loosely coupled code to handle the processing of errors and pass in the implementing codeunit as required:

codeunit 50103 "Error Creator"
{
    procedure ProcessError(ErrorHandler : Interface IErrorHandler)
    begin
        ErrorHandler.HandleError('Error1', 'This is an error message!');
    end;

    procedure CallErrorHandler(PersistErrors : Boolean)
    var
        ErrorLogCU : Codeunit "Log Errors in Database";
        ThrowErrorCU : Codeunit "Throw Error";
    begin
        If PersistErrors then
            ProcessError(ErrorLogCU)
        else
            ProcessError(ThrowErrorCU);
    end;
}

The ProcessError() method above takes a parameter of type Interface IErrorHandler, this means we can pass in any codeunit that implements IErrorHandler as seen in the CallErrorHandler() method.

A codeunit can implement multiple interfaces using comma separation:

codeunit 50105 "Log Errors in Database" implements IErrorHandler, ISomeOther, ISomeOther2
{
   // implementation here...
}

Note: The I prefix on the interface name is not mandatory but is a common convention used in C#.

The interface type was revealed during the NAVTechDays 2019 opening keynote, which is now available on YouTube here (1:17:30).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.