INTERFACE usage
Defining interfaces
An interface is defined by a group of methods that apply on user-defined types, to define a common usage interface for several individual types.
A method declared in an interface must use the same parameter names, parameter types and return types as the method implementation it refers to.
TYPE
declaration:TYPE Shape INTERFACE
kind () RETURNS STRING,
area () RETURNS FLOAT
END INTERFACE
A variable defined with an interface type can receive any type related to the interface.
Associating types to an interface
A user-defined type for which methods are defined is implicitly associated to any interface that defines a set of methods for this type.
Rectangle
gets associated to a method named
area()
:TYPE Rectangle RECORD
height, width FLOAT
END RECORD
FUNCTION (r Rectangle) area () RETURNS FLOAT
RETURN r.height * r.width
END FUNCTION
area()
method becomes implicitly an interface for
the type
Rectangle
:TYPE Shape INTERFACE
area() RETURNS FLOAT
END INTERFACE
v
with an INTERFACE
structure listing
the area()
method, you can assign a variable defined as Rectangle
to v
, and invoke the method with
v.area()
:FUNCTION main()
DEFINE r Rectangle = ( height:10, width:20 )
DEFINE v Shape
LET v = r
DISPLAY v.area()
END FUNCTION
Implementation tips
Write generic code in functions taking as parameter interfaces or collection or interfaces (dynamic arrays, dictionaries).
For maximum flexibility, consider implementing the types and corresponding methods in individual
modules, and implement the interface in another individual module. In the parent module using the
types/methods and interfaces, import each module with the IMPORT FGL
instruction.
Interface referencing an unexisting record
An INTERFACE
variable references a RECORD
variable using a
TYPE
. If the life time of the referenced RECORD
is over (for
example, when using the RECORD
variable defined in a function returned as an
INTERFACE
from that function), the runtime system will raise the error -8083, when
calling a method of this INTERFACE
variable, because the variable is no more
existing.
TYPE my_interface INTERFACE
method_1() RETURNS ()
END INTERFACE
TYPE my_record_type RECORD
num INTEGER
END RECORD
FUNCTION (r my_record_type) method_1() RETURNS ()
DISPLAY r.*
END FUNCTION
FUNCTION foo() RETURNS my_interface
DEFINE rec my_record_type -- implements my_interface
RETURN rec -- this returns an INTERFACE to a local variable
END FUNCTION
FUNCTION main()
-- when calling method_1, the INTERFACE tries to access the rec RECORD
-- which is no longer available.
CALL foo().method_1() -- expected runtime error -8083
END FUNCTION
Program stopped at 'm.4gl', line number 21.
FORMS statement error number -8083.
Null pointer exception.