Shared behavior in GDScript #12498
Squeeshy123
started this conversation in
Scripting
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
'Prefer composition over inheritance' is a notion strongly pushed by Godot, its source code (to my knowledge, but correct me if I'm wrong), and many members of the community. This is a phenomenal design pattern, yet I feel that GDscript is so unsupportive of this design principle. Sure, we have duck typing, but that seems like the poor man's approach to shared behavior, as it requires more responsibility on the classes who are calling methods on other classes to make sure they get the name of the method correct, and also the parameters of the method correct. To check if there is some behavior, one must use the
has_method()
method, and go from there, but this requires you to get the name right, or else you could face a difficult to track bug. If there were something like an interface, or algebraic data types, then the compiler gets to do a lot more work for the programmer, and prevent a lot of human error.I appreciate the light shed on this topic from this post, (if you need an example for what I'm talking about, look at that post) yet the conclusion ended up being "compose your scenes over using inheritance trees," which was a rather unsatisfying conclusion, as that solution can't really apply to things that aren't nodes. Additionally, if I'd like to create behavior when certain types of nodes relate (i.e if I have a fire pit, and I want to catch flammable things on fire), I'd have to dig through another node's tree to search for flammable behavior, or go back to square one and do
has_method()
if I put that in the parent node. Depending on the implementation, these approaches can easily lead to breaking the Law of Demeter, which introduces coupling.Just my thoughts on some approaches:
Interfaces
This is easily the best way to fix this issue. Having publicly facing promises that makes objects that implement an interface say "I have this behavior"
The discussion about this is done well in #4872
Public Macros
Surely a weird thought that I had, but with the lack of extensibility in gdscript, it would make sense to have some way to add syntactic features. A potential way to create interfaces using macros would be to create a public macro that accepts blocks of code for each behavior there is, so for example:
Then in the implemented class:
This still requires one to use
has_method("impls_fire")
but the difference is that since the behavior has been declared in one place, it gets easier to catch errors. But, depending on the macro system, this problem could be avoided.This syntax obviously isn't ideal, but the idea is what I'm concerned with. This system is EASILY more clunky than a simple interface, but for discussion purposes, I wanted to bring it up.
GDExtensions that can mod GDScript
This is another more general solution, and my knowledge on this topic is more limited, but by allowing GDScript to be extended, features like interfaces, algebraic data types, and type parameters can be implemented.
Granted all of these can be solved by "using another language" like Rust, but nothing has nearly as much support, nor convenience as GDScript.
Beta Was this translation helpful? Give feedback.
All reactions