Business Central 2024 wave 2 (BC25): Extend AL interfaces

Dynamics 365 Business Central

Hi, Readers.
The public preview for Dynamics 365 Business Central 2024 release wave 2 (BC25) is available. Learn more: Link.

I will continue to test and share some new features that I hope will be helpful.

Extend AL interfaces:

Business value:
The support for extensible interfaces in programming languages offers significant business value by enabling creation of flexible and adaptable extensions that can evolve over time to meet changing business needs. They enable developers to add new functionalities without altering the core system, which can save time and resources while reducing the risk of introducing errors into the existing codebase. They are a key component in modern software engineering, providing the agility and flexibility needed to drive innovation and maintain a competitive edge in today’s fast-paced business environment.

https://learn.microsoft.com/en-us/dynamics365/release-plan/2024wave2/smb/dynamics365-business-central/extend-al-interfaces?wt.mc_id=DX-MVP-5004336

An interface in AL is similar to an interface in any other programming language; it’s a syntactical contract that can be implemented by a nonabstract method. The interface is used to define which capabilities must be available for an object, while allowing actual implementations to differ, as long as they comply with the defined interface. More details: Interfaces in AL
This was a new object type in Business Central 2020 Wave1 (BC16).

The interface declares an interface name along with its methods, and codeunits that implement the interface methods, must use the implements keyword along with one or more interface names. The interface itself doesn’t contain any code, only signatures, and can’t itself be called from code, but must be implemented by other objects. Let’s look at a simple example.

1. Create a new interface object: Procedure with declaration only

2. Create a codeunit that implements this interface: declare the code of the procedure

The name and number of the procedure, whether it has a return value, and the type of the return value must be the same as defined in the interface object. Otherwise an error message will be displayed.

‘ImplementZYTest’ does not implement the interface member ‘ZYTestInterface.ShowMessage’. AL AL0582

And

‘PrivateAddressProvider’ does not implement the interface member ‘IAddressProvider.GetAddress2’. AL AL0582

3. Use the new Interface object:

Please note that if you do not specify which codeunit to read before calling the interface, the following error will be prompted.

Interface not initialized

There are two more special initialization ways:
1. Pass codeunit directly as a variable to the function

2. By Enum object: This is useful for situations where there are multiple procedures

Test code:

interface ZYTestInterface
{
    procedure ShowMessage()
}

codeunit 50102 ImplementZYTest implements ZYTestInterface
{
    procedure ShowMessage()
    begin
        Message('Hello World');
    end;
}

pageextension 50100 CustomerListExt extends "Customer List"
{
    trigger OnOpenPage()
    var
        ZYTestInterface: Interface ZYTestInterface;
        ImplementZYTest: Codeunit ImplementZYTest;
    begin
        ZYTestInterface := ImplementZYTest;
        ZYTestInterface.ShowMessage();
    end;
}

Let’s look at a more complex example. (I modified the Microsoft example a bit)
The first is the definition of interface and codeunit. This time there are two codeunits implemented to the same interface.

The same interface is executed in two different actions, but the initialization codeunit is different.

Great.

PS: Interface example from Microsoft Learn

Let’s get back to the topic, with this wave (BC25), you can now extend one or more existing interfaces when you declare an interface. When implementing an interface that extends other interfaces, the implementor must also implement all methods from all extended interfaces.

For example, the TheImplementor can be used as both IFooIBar, and IFooBar.

Let’s try extending the interface from the previous example.
1. Extend the interface

2. Create a mew codeunit that implements the interface extension: All procedures in the source interface must be implemented

3. Use the new Interface extension: Newly created codeunit and interface extension must be declared.

Additionally interfaces are already widely used in standard, such as Email and New sales pricing experience modules. Please also consider this new approach when customizing your own functions.

Great, give it a try!!!😁

PS:
1. Interfaces can be obsoleted like other AL object types by using the ObsoleteState, ObsoleteReason, and ObsoleteTag properties and the Obsolete attribute. This approach can help with the process of managing interface change.

2. The feature also works with the testing and casting operators is and as, which are also new additions to the AL language in this release. More details: Business Central 2024 wave 2 (BC25): Type testing and casting operators for interfaces (‘is’ operator and ‘as’ operator)

Test code:

interface IAddressProvider
{
    procedure GetAddress(): Text;
}

interface IAddressProviderExt extends IAddressProvider
{
    procedure ShowMessage();
}

codeunit 50100 CompanyAddressProvider implements IAddressProvider
{
    procedure GetAddress(): Text;
    begin
        exit('Company address \ Denmark 2800')
    end;
}

codeunit 50101 PrivateAddressProvider implements IAddressProvider
{
    procedure GetAddress(): Text;
    begin
        exit('My Home address \ Denmark 2800')
    end;
}

codeunit 50102 ShowMessageProvider implements IAddressProviderExt
{
    procedure GetAddress(): Text;
    begin
        exit('My Home address \ Denmark 2800')
    end;
    procedure ShowMessage();
    begin
        Message('Hello World');
    end;
}



pageextension 50100 CustomerListExt extends "Customer List"
{
    actions
    {
        addafter(ApplyTemplate)
        {
            action(ShowHomeAddress)
            {
                ApplicationArea = All;
                Image = Home;
                Caption = 'Show Home Address';
                Promoted = true;
                PromotedCategory = Process;
                trigger OnAction()
                begin
                    iAddressProvider := PrivateAddressProvider;
                    Message(iAddressProvider.GetAddress());
                end;
            }

            action(ShowWorkAddress)
            {
                Image = WorkCenter;
                Caption = 'Show Work Address';
                ApplicationArea = All;
                Promoted = true;
                PromotedCategory = Process;

                trigger OnAction()
                begin
                    iAddressProvider := CompanyAddressProvider;
                    Message(iAddressProvider.GetAddress());
                end;
            }
            action(ShowMessage)
            {
                Image = WorkCenter;
                Caption = 'Show Message';
                ApplicationArea = All;
                Promoted = true;
                PromotedCategory = Process;

                trigger OnAction()
                begin
                    iAddressProviderExt := ShowMessageProvider;
                    iAddressProviderExt.ShowMessage();
                end;
            }
        }
    }
    var
        iAddressProvider: Interface IAddressProvider;
        iAddressProviderExt: Interface IAddressProviderExt;
        CompanyAddressProvider: Codeunit CompanyAddressProvider;
        PrivateAddressProvider: Codeunit PrivateAddressProvider;
        ShowMessageProvider: Codeunit ShowMessageProvider;
}

END

Hope this will help.

Thanks for reading.

ZHU

コメント

Copied title and URL