godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add an `@override` annotation to GDScript #10586

Closed Sheep26 closed 2 weeks ago

Sheep26 commented 2 weeks ago

Describe the project you are working on

I've been working on a dungeon crawler in Godot. I'm making a enchantment station where there's a base_enchantment class and signal would be linked to a builtin function inside the base_enchantment class, said function would be overridden in a child/extention of the base_enchantment class.

Describe the problem or limitation you are having in your project

The limitation is where a child can't override the arguments off a parents builtin function.

class Base_Enchantment:
    var event: Signal
    var enchantmentCost: int
    var bought: bool
    var enchantmentName: String
    var player: Player

    func _init(_player: Player, _event: Signal, _mutationCost: int, _mutationName: String):
        self.player = _player
        self.event = _event
        self.mutationCost = _mutationCost
        self.mutationName = _mutationName

    func buy():
        bought = true
        event.connect(handle)

    func handle(_arg0): pass

class ThornsMutation:
    extends Mutation

    func handle(enemy: Enemy, amount: float): # Error here
        enemy.take_damage(amount / 4)

Now func handle(enemy: Enemy, amount: float): doesn't match the parents version of such function, in other languages there is an @override annotation which would make this code to work if added into Godot.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

@override allows a class extending off another class to override a builtin function in said parent class, this allows arguments and return types to differ from parent to child.

This would overcome the limitation as it would allow the function to keep the same name allowing it to be handled from the base script while having different arguments to be handled by a signal.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

This would work like any other annotation for a function

An example of which is:

@override
func handle(enemy: Enemy, amount: float):

If this enhancement will not be used often, can it be worked around with a few lines of script?

There isn't currently isn't a work around to be able to do this in Godot 4.3. This would be an enhancement because it would allow event systems and consoles to be built much easier.

Is there a reason why this should be core and not an add-on in the asset library?

This wouldn't work if added to the asset library because the gdscript source code would need to be edited (which I have already started doing).

dalexeev commented 2 weeks ago

@override allows a class extending off another class to override a builtin function in said parent class, this allows arguments and return types to differ from parent to child.

Usually oveload has a different meaning, see:

It seems you are trying to achieve something like function overloading (#1571), but with method inheritance and without proper checks.

Arbitrarily replacing the number of arguments in a method signature when overriding a method violates the Liskov Substitution Principle. If the original method takes [N, M] arguments, then the overriding method must take [P, Q] arguments, where P <= N <= M <= Q, to preserve argument contravariance (also return type must be covariant). This is already implemented in my variadic functions PR (godotengine/godot#82808), you can do it like this:

class A:
    func f(a, b, c): pass # [3, 3]

class B extends A:
    func f(a, ...args): pass # [1, ∞]