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.
Business value:
https://learn.microsoft.com/en-us/dynamics365/release-plan/2024wave2/smb/dynamics365-business-central/extend-al-interfaces?wt.mc_id=DX-MVP-5004336
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.
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 IFoo
, IBar
, 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
コメント