Interfaces - coldrockgames/gml-raptor GitHub Wiki
Raptor offers some interfaces for you to implement into your objects.
Interfaces in GML
Well, GML does not have interfaces. But raptor does. Kind of. But not in the C#/Java/OO style. But close to.
There are two functions available in raptor for your interfaces:
What is an Interface in Raptor?
- It is a constructor function. You can make any constructor an interface.
- It has an (optional)
ctor
function (there's a raptor macro for it), which will be executed after the interface has been applied on the target instance/object. - It may declare any functions and they will be added to the instance or object, the interface is implemented on.
- It may even declare variables, but this should be done in the
ctor
function, as that one gets executed in the context of the already vital target instance.
Example of an interface
function ILoggable() constructor {
ctor {
__log_string = undefined;
}
get_log_string = function() {
if (__log_string == undefined)
__log_string = $"{MY_CLASS_NAME} {some_variable} {some_status}";
return __log_string;
}
}
Now imagine, you have a game object (or struct class) which shall implement that interface to create standardized log messages. You would do it like this:
// CREATE EVENT of a game object
event_inherited();
implement(ILoggable);
function my_code_class() constructor {
implement(ILoggable);
}
What happens here?
- The
implement
function creates an instance ofILoggable
by invoking the constructor. - This instance is then
struct_join
ed into the current object. This means, all functions and members of the interface function will be transferred to the target instance. Methods will be rebound usingmethod(...)
to inherit the new scope. - Then the
ctor
function is invoked (if it exists). - After executing,
ctor
is removed from the instance.
flowchart TD
A["implement(ILoggable)"] --> C["inst = New ILoggable();"]
C --> D["struct_join(target, inst);"]
D --> E[Add to interfaces list]
E --> F{"ctor exists?"}
F -- Yes --> G["ctor();"]
G --> H["struct_remove(self, ctor);"]
H --> I
F -- No --> I[end]
Interface Implementation Functions
As you can see in the jdoc below, interface functions may even have arguments! You can use any constructor in your game as interface to rebind it (or: implement it) in any other instance, no matter whether it's a code class or a game object.
implement(interface_type)
/// @func implement(_interface, ...constructor_arguments...)
/// @desc Works like an interface implementation by copying all members
/// and re-binding all methods from "interface" to "self"
/// Creates a hidden member __raptor_interfaces in this struct which contains
/// all implemented interfaces, so you can always ask "if (implements(interface))..."
/// NOTE: Up to 15 constructor arguments are allowed for "_interface"
/// This function will create one instance and copy/rebind all elements to self.
function implement(_interface) {
implements(instance, interface_type)
This is the reflection counter-part, telling you, whether a specified instance implements the specified interface_type. You may supply the interface_type either as a string (name of the class) or the type.
Although the first argument is named struct
, this works for game objects as well, as they are kind of a struct too.
/// @func implements(struct, _interface)
/// @desc Asks the specified struct whether it implements the specified interface.
function implements(struct, _interface) {