Overview of Interfaces¶
An interface declares a runtime-dispatched function surface. An implementation binds that surface to concrete functions.
Interface declarations¶
::integer_source INTERFACE DEFAULTABLE
{
.read FUNCTION(): I32;
.fallback FUNCTION(@ARG:value I32): I32
{
RETURN value + 100;
}
}
An interface member may be a signature ending in ; or may include a default
body. Overloaded member names are allowed when their signatures differ.
DEFAULTABLE permits a default or NULL interface handle. A default method can
still be called on an empty defaultable handle when its body does not require a
concrete implementation slot.
Implementations¶
::integer_source_impl IMPLEMENTATION(integer_source)
{
::read FUNCTION(): I32
{
RETURN 7;
}
::fallback FUNCTION(@ARG:value I32): I32
{
RETURN value + 1;
}
}
Implementation functions use nested ::name declarations matching interface
members. A required signature that is missing or incompatible makes conversion
to the interface invalid.
Interface handles¶
VAR source integer_source := integer_source_impl;
ASSERT(source??);
ASSERT(source.read() == 7);
ASSERT(source.fallback(4) == 5);
VAR empty integer_source;
ASSERT(empty!?);
ASSERT(empty.fallback(4) == 104);
Handles are copyable values. Assigning an implementation symbol selects that
implementation; assigning NULL clears a DEFAULTABLE handle. Member calls
dispatch through the current implementation or use the interface default body.
See Generics for owning and non-owning type erasure of objects.
Reference¶
See the Interfaces and Implementations Reference for the complete language rules, constraints, and technical edge cases.