Does GDScript have Interfaces and/ or abstract classes?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By TheHaecker
:warning: Old Version Published before Godot 3 was released.

Does GDScript have Interfaces and/ or abstract classes?
Can’t find anything about this topic online.

:bust_in_silhouette: Reply From: eska

GDScript doesn’t have those kinds of features, this is by design. For GDScript’s purposes, they’re unnecessarily complex.

Instead, GDScript is perfectly suited for duck-typing. This is also explicitly recommended in the documentation: GDScript: An introduction to dynamic languages — Godot Engine (stable) documentation in English

So whenever you would use interfaces or abstract classes in Java/C#/etc, you’ll want to use something like:

if obj.has_method('func_name')`:
    obj.func_name()

Perfect, thanks! I didn’t realize that there’s no need for interfaces in scripting languages, but this makes sense to me.

TheHaecker | 2017-10-20 12:07

Checking if an object has the method every time you call every “custom” method on every object, is a bit awkward, to say the least. Imagine having dozens of calls and multiply the “every”'s. It’s exponential growth of code.
Additionally, interface would’ve kept objects organized just like inheritance.

snwflk | 2017-12-12 13:06

@snwflk exactly. And interfaces were designed exactly to solve this problem. They define - well - an interface, or a contract, between the users of the class and the class itself, that specifies what methods and attributes are there and can be called without specifically asking if they’re actually there - thanks to the interface, it’s guaranteed for them to be there. And to the fans of duck typing, I use to tell:
    Duck typing is “F*ck typing!” :stuck_out_tongue:
because it’s pretty much that: it ignores the types whatsoever, as in the old days of assemblers and raw memory accesses, and relies on figuring out the object’s layout only in runtime, on your own. Which is pretty terrible coding practise if you ask me :q

SasQ | 2017-12-13 11:37

@SasQ I miss the voting comments feature from StackOverflow and Unity Q&A…

I just hate dynamic typing myself for casting issues and for arguments stated in here: https://godotdevelopers.org/forum/discussion/18770/is-specifying-type-possible-in-gdscript
This and duck typing are, like visual scripting, meant for artists to connect assets, not for programmers.

Anyway, reading the official documentation I found this

Initially, Godot was designed to support multiple scripting languages
(this ability still exists today).

and it made me feel a little… downcast, since I like Godot initial design.

snwflk | 2017-12-13 13:49

sorry but it’s a known fact interfaces are best practices in OOP

I feel like “duck-typing” gets us back to good old zillion lines of basic codes in one file…

phil1234 | 2021-05-20 19:24

:bust_in_silhouette: Reply From: snwflk

I suppose you need interfaces/abstract classes for organizing complexity and type enforcement.
As @eska well mentioned, GDScript is made with simplicity in mind, hence no interfaces and no static type.
You could make an abstract class by just making a regular class and just not instantiate it but only extend from it. I do that to keep things organized. You’re not constrained to not instantiate it, of course (which is good and bad).
My advice:

If you aim for a project of a size requiring these features, consider using the alternatives - C++, C#.

Otherwise you should be fine without checking for method existence, since you’d only have a handful of classes and methods.

Another way to consider is using signals.

If you’re not satisfied with either of the approaches above, then whenever you want to implement an interface you’d make a dummy static method like static func implementsCrushable():pass
in the classes you want to implement the so called “interface”, without any such “interface” actually existing.
Then whenever you’d call various methods on an object o you’d write:

if o.has_method("implementsExplodable"):
    if o.has_method("implementsCrushable"):
        o.stainRoad()
        points = o.pointsGranted # only crushable explodables grant points
    else:
        o.damage(self)
        o.stainRoad() # homonym method of non-crushable explodable
        ...
        o.explode()

This way you only need to check once for all (not each) of the methods of that “interface” when you call them. Plus you can see what is what.

Just use groups to define your “interfaces”, make every node in specific group be certain of having a method or variable, problem solved :smiley:

eons | 2017-12-14 19:27

That is overkill when you have a logical model that is code only. It’s now two projects I’ve wanted to use structures with no direct representation in any scene and are instantiated arbitrarily.

MaxLittlemore | 2023-01-25 07:57

This is a cool workaround but it doesn’t provide the main benefits of “real” interfaces. One could still “implement” Crushable without implementing a necessary crush() function of the interface, leading to crashes during run-time.

chibi-dev | 2023-06-20 16:44

:bust_in_silhouette: Reply From: gon123

I’m starting with Godot 4 and I have been programming in OOP for years, so some times I feel like I kinda need interfaces, inheritance, etc.

Right now I’m implementing a very generic inventory (we could call it container or slot container, for inventories, boxes, quickbars, hotbars, etc) and I really want to have the responsabilities well distributed.

May be I should use C# or C++ but I started learning godot with GDSCript and I’m on fire, so my approach right now is use composition and inheritance, as there is no interfaces or abastract classes, what I’m doing is implementing abstract methods with a “pass” body and may be a print message.

TL;DR: Use inheritance and composition, implement abstract methods con parent with an empty body, for example.

Parent class:

class_name Animal
walk():
    print("Method not Implemented) # You could throw an error
    pass

Child class:

class_name Dog
extends Animal

walk():
    print("Walk speed of 8 km/h")

This thread is very old, but I’m going to throw my opinion into here anyway.
I am also not a fan of duck typing. There is absolutely nothing in GDScript that prevents using good OOP design principles such as interfaces. GDScript won’t help you, as you will be responsible for ensuring your interfaces act as interfaces, but it also won’t stop you. I usually end up less with interfaces and more with inheritence, but it works fine.

I frequently have usage trees such as: Weapon → Projectile Weapon → Handgun. Weapon has all the code common to all weapons, Projectile Weapon has all the code common to projectile weapons, and Handgun has all the code specific to handguns.

Sometimes I end up with a Weapon base class that leaves decision making to the subclass, so the Weapon implementation method consists of the method name and a “pass” body. The subclass implementation then overrides the Weapon base class.

stormreaver | 2023-03-29 01:56