Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow child class to override parent constant #24879

Closed
e-e opened this issue Jan 10, 2019 · 11 comments
Closed

Allow child class to override parent constant #24879

e-e opened this issue Jan 10, 2019 · 11 comments

Comments

@e-e
Copy link

e-e commented Jan 10, 2019

I propose gdscript should allow for a child class to override constants declared in the parent class. It seems like a very common use case for a child class to inherit all the same functionality of the parent, but with differing parameters to provide differing behaviors. As it is currently, a class becomes unextendable with the declaration of a constant whose value is not suitable for every single potential child. A trivial example:

# Turtle.tscn

extends Node

const SPEED = 1

func move():
    # some move code utilizing SPEED

func do_turtle_things():
    # ...
# FasterTurtle.tscn

extends "res://Turtle.tscn"

const SPEED = 100

Without this functionality, it seems one is forced to use a non-constant value instead, setting the child class' value in the _init() method, even if you never intend to change SPEED at runtime.

@isaacremnant
Copy link
Contributor

Seems like export(int) var SPEED = 1 would be a better solution to your use case. Since it's exposed to the editor, you won't have to explicitly change the variable from the derived class.

@groud
Copy link
Member

groud commented Jan 10, 2019

Well, if a constant can see its value modified by children it is not a constant anymore.
But in general, in object-oriented language, you cannot even override normal class attributes. Only functions can be overridden.

So IMHO, what you propose is quite a bad practice in general, as it creates several versions of a constant with differents values (which is the opposite of a constant) .

@ghost
Copy link

ghost commented Jan 10, 2019

#23695

@akien-mga
Copy link
Member

Indeed, as mentioned by @isaacremnant you should use export(int) var SPEED for this use case, it does exactly what you're asking for. If you want the constant to be overridable, you don't want it to be a constant :)

@CptTony303
Copy link

There is a need for this Usecase:
When you need static access you need a constant.
the Code below wont work right now (its also just for understanding and wrong syntax)

class Vehicle
const wheels = null

class Bus extends Vehicle
const wheels = 6

class Bike extends Vehicle
const wheels = 2

When we want to check how many wheels a bike has, we won't need to create a new Bike instance to check this.
It is constantly 2 and never changes.

Reopen issue please?
Or allow const for export :P

@Calinou
Copy link
Member

Calinou commented Nov 10, 2020

@CptTony303 Feature proposals should now be discussed in the Godot proposals repository. But first, keep in mind:

Well, if a constant can see its value modified by children it is not a constant anymore.
But in general, in object-oriented language, you cannot even override normal class attributes. Only functions can be overridden.

@droqen
Copy link

droqen commented Dec 3, 2020

There is a need for this Usecase:
When you need static access you need a constant.

In your specific use case, static access, there is no need for the Vehicle parent? Unless I misunderstand a particular way to access static variables, you'd never refer to Vehicles generically -- you'd always explicitly write 'Bike.wheels'.

So, you can safely just exclude 'const wheels = null' from class Vehicle.

@e-e
Copy link
Author

e-e commented Dec 10, 2020

@akien-mga

Indeed, as mentioned by @isaacremnant you should use export(int) var SPEED for this use case, it does exactly what you're asking for. If you want the constant to be overridable, you don't want it to be a constant :)

@Calinou

Well, if a constant can see its value modified by children it is not a constant anymore.

It should still be treated as a run-time constant, which is the important part. I agree with @CptTony303 and feel that their example very clearly outlines the usefulness of a feature such as this.

@frozenMustelid
Copy link

I just ran headfirst into this limitation. I'm trying to make a dictionary that holds all the monster scenes - This should make creating/editing random encounter tables much easier. A key has to be a constant, which means that my monster template scene can't define or even declare this necessary piece of data. It also means that I can't have upgraded monsters (common example: early game has regular spiders, late game has fiendish spiders) inherit from the original or base version of the monster, because then they'd share the same dictionary key.

I guess it's either back to the drawing board, or just bite the bullet and do it the annoying (read:less maintainable) way.

@Kiramin
Copy link

Kiramin commented Dec 9, 2021

I second this feature.

Here is an explanation of why this doesn't violate good practices for constants:

Well, if a constant can see its value modified by children it is not a constant anymore.

That would indeed be a problem. But that isn't what happens; the parent class is not modified. Its const value remains unchanged. No values are changing during runtime for either class. Everything remains constant. Hence, no issues will be caused in multi-threading etc. This feature is just a major labor saving device. Consider this: You could manually type out two classes, a "Bike" class and a "Truck" class, and you could fill them with 90% of the same code, save a few differing const values. Everything remains constant, and the program runs fine. But, if this feature existed, then you could save yourself all that trouble, write one Vehicle class, and inherit from it twice, with a few const overrides and function overrides. This has an identical effect as writing two classes from scratch, but saves you a lot of work and ugly code duplication (which itself is a bad practice). Without this feature, you can still approximate this as is, by creating a function called "get_num_wheels()" and override it for Bike and Truck respectively. Of course, then a function has to be called every time to get the value, which is unnecessary overhead, because the value never changes. Hence, since it doesn't change, is shared between all instance of a class, and doesn't need to be calculated, it should be stored in a const, and not a var, nor a function.

Peace.

@Tramis
Copy link

Tramis commented Jan 29, 2023

i have the same problem. im using static function instead

class A:
    # const a = 1
    static func a():
        return 1

class B extends A:
    # const a = 2
    static func a():
        return 2

sorry for that im not familiar with dynamic typed language, in my view, a const value is bind to a specific type, just as same as static functions. and A is definitily a different type with B

so it looks weird for me. since static function can be overwrited but const can't. Did i consider something wrong with const ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants