Interface
An interface is often considered a 'contract'. The interface declaration defines the signature of methods and properties, but does not define any implementation. Any function block can IMPLEMENT any number of interfaces by ensuring that they declare and provide an implementation for all members of the interface.
A variable (or parameter) can be assigned an interface type again without knowing the underlying implementation.
Syntax
INTERFACE <InterfaceName>
// Method Signatures
METHOD <MethodName> : <ReturnType?>
// (No body, only inputs, inout, output)
END_METHOD
END_INTERFACE
Sample
In this sample, we define an interface for a math operation that has a single method M_Execute. This method is responsible for executing some unknown mathematical operation. We also define a single implementation for a function that adds the two input values.
INTERFACE IMathOperation
METHOD M_Execute : INT
VAR_INPUT
IN1 : INT;
IN2 : INT;
END_VAR
END_METHOD
END_INTERFACE
FUNCTION_BLOCK FB_Add IMPLEMENTS IMathOperation
METHOD M_Execute : INT
VAR_INPUT
IN1 : INT;
IN2 : INT;
END_VAR
M_Execute := IN1 + IN2;
END_METHOD
END_FUNCTION_BLOCK
VAR
val : INT;
itf : IMathOperation;
inst : FB_Add;
END_VAR
itf := inst;
val := itf.M_Execute(2, 3);
Here we have another implementation of the IMathOperation interface where we subtract the values. We can also piece this together
FUNCTION_BLOCK FB_Subtract IMPLEMENTS IMathOperation
METHOD M_Execute : INT
VAR_INPUT
IN1 : INT;
IN2 : INT;
END_VAR
M_Execute := IN1 - IN2;
END_METHOD
END_FUNCTION_BLOCK
VAR
val : INT;
itf : IMathOperation;
instAdd : FB_Add;
instSub : FB_Subtract;
END_VAR
itf := instAdd;
val := itf.M_Execute(2, 3); // 5
print(val);
itf := instSub;
val := itf.M_Execute(2, 3); // -1
print(val);
In order to implement the interface, we only require a method that matches the signature. Here is an implementation that always returns the same value no matter what the inputs are.
FUNCTION_BLOCK FB_NoOp IMPLEMENTS IMathOperation
METHOD M_Execute : INT
VAR_INPUT
IN1 : INT;
IN2 : INT;
END_VAR
M_Execute := 0;
END_METHOD
END_FUNCTION_BLOCK
VAR
val : INT;
itf : IMathOperation;
inst : FB_NoOp;
END_VAR
itf := inst;
val := itf.M_Execute(2, 3); // 0