Godot Version
4.3 Stable
Question
Hello! So I’m currently learning to inject dependencies in Godot and I’m trying to wrap my head around the best way to inject functions in a child node. In particular, I’m curious as to the best way to check if a child wants a function. Right now, I have it set up so that the child declares several callable properties i.e.:
The parent node then checks if its children have these properties using a String, and if it does, injects its own method into them i.e.:
While this works fine, I don’t like using Strings here. I keep thinking that there must be a better way. For example, I would prefer to compare StringNames using:
Object.has_method(name : StringName) → StringName
but declared child functions can’t be overriden as they’re constants, so I have to declare them as variables. And while there is a function:
Callable.get_method() → StringName
It still requires that I have a reference to the Callable in order to call get_method() on it. And I don’t have a reference to the Callable from the parent.
Any suggestions would be highly appreciated
1 Like
you can create a dictionary that contains all needed callables and use dict functionality to filter/check/update/remove.
why not to:
var callables:={
'add_scene':func():add_child(load('res://path').instantiate())
}
#to check if it has or not
if 'func_name' in callables:
callables['func_name']=remote_callables_dict['func_name']
best way to ‘inject’ anything to node is to use methods
_get_property_list()
_set()
_get()
2 Likes
I see! This is a clever solution. I guess my only question would be, is getting the entire property list more expensive than simply doing a String comparison?
I’m not sure how “in” is implemented, but assuming its basically _get(), is the primary advantage to validating the property list organizational? I’m assuming there would be a small performance penalty, although since this only happens on _ready()/init it’s not that big of a deal.
if you used debug remote, get_property_list() called every time you click on object and to update getters.
in works with everything that could be an array. You may even use in on object to check if property exist in object and is shortcut to dict.has(key)
properties by default are converted to StringName(s). You may use it in dictionary
defining &‘key_name’ and access is dict[&'key_name']
NOT dict.key_name
.
_get() works as rerouter for property when requested and can be used to create invisible getter and emit signals if needed.
1 Like
Thank you for the help, you’ve given me some idea as to the direction I’ll take going forward. For now, I’m going to use the simple solution you’ve suggested and just do something like this:
That being said, this really is a stop gap.
I am beginning to see how your solution can be used in combination with @export to be able to define the name of the callables in-editor i.e.:
which really allows for maximum flexibility. Each “Interface” can have its own callable_list resource that a parent parses for methods to “inject” it with.
1 Like