-
-
Notifications
You must be signed in to change notification settings - Fork 97
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 overriding a member variable's type in inherited classes #4686
Comments
Are there other programming languages allowing this? To me, it sounds like this breaks OOP principles. |
What would an actual use-case for this even be? It doesn't just break programming standards, but it could be avoided outright by not defining a member variable's type, keeping it a Variant. |
@Calinou in Python it's possible to reach that behaviour. Of course Python it is not a static typed language, but it's feasible. |
For example, let's imagine we need some complex character int and float stat class. If try to do it now like this: extends Node
class StatBase:
var base
var max
var val
func _init(params: Dictionary = {}):
base = params.get('base', 0)
max = params.get('max', 0)
val = params.get('val', 0)
func setv(value):
val = clampf(value, 0, max)
func add(value):
val = clampf(val + value, 0, max)
func sub(value):
val = clampf(val - value, 0, max)
func is_full():
return val >= max
class IntStat:
extends StatBase
func setv(value: int):
super.setv(value)
func add(value: int):
super.add(value)
func sub(value: int):
super.sub(value)
class FloatStat:
extends StatBase
func setv(value: float):
super.setv(value)
func add(value: float):
super.add(value)
func sub(value: float):
super.sub(value)
func _ready():
var int_stat: IntStat = IntStat.new()
int_stat.max = 1.5
var float_stat: FloatStat = FloatStat.new()
float_stat.val = 'text' It's possible even override functions with type hint for arguments. But there is still remains some problems:
|
This looks like something generics are for (which GDScript lacks). |
Related: Overriding the type is a bad idea, it violates the Liskov substitution principle. |
Okay. I think i was not clearly enough to convey my point of view. I don't need to change already defined types to a different. I just need ability to define variable without type in parent class and define type later in inherited classes. The goal of it is:
In this case inherited classes can change variables types only inside themselves. So i think it can't break anything in parent class and in logic inherited from parent class (because that logic don't rely on a variable type). I mean it's not overriding one type to another. I consider it as extending existed functionality with specifying a type to a variables without type. Yes, maybe it can break something if try to use that inherited class instead of parent class (substitution). But in my case that's will never be happened. Because in this case parent class is just only a base class that not designed to be used directly at all. So how about that? Substitution principle can be violated even without this proposal. Just with methods overriding. But methods overriding is legit by itself. Therefore violation dependent on how technology are used, not on which technologies are available. In my case i think it's possible to use it without violation and with profit. |
There are no variables of undefined type. Type narrowing (for example, class A:
var x: Variant
class B extends A:
@override var x: int
# The static type of obj is A, and the actual value is type B,
# which inherits A. The code here doesn't need to know anything
# about subtypes of A, it could be func f(a: A) that was passed
# an object of class B.
var obj: A = B.new()
# According to the substitution principle, this is a legal operation,
# since A.x is Variant, the editor should mark this line as type safe,
# and the compiler cannot find an error here statically.
# However, with the proposal, there will be a runtime type error here!
obj.x = "test"
This may sound harsh, but we're not just talking about your case here. We are thinking about how this proposal will affect the language as a whole.
Yes, because the meaning of a type is more than just
Of course, in practice there are exceptions to any principle. They are caused 1. by the fact that the principle itself is not universal and in some cases, on the contrary, harms, 2. by the fact that we sometimes have no time to understand our mistakes and design an ideal system. Personally, I consider the substitution principle to be one of the most basic and important principles in programming. It comes from the laws of mathematics, not subjective human preferences. If I ever violated this principle, then I think all these cases relate to p. 2. In my opinion, this principle is too important for us to create tools that allow its violation where it was previously impossible. Probably what you are asking can be solved with abstract/virtual properties (and abstract classes), with generic methods and/or parametric types. The last two are unlikely to appear due to GDScript's dynamic typing, but perhaps |
Ok. I just wanted to propose a some addition what can be useful in some cases if use it right. If you don't want it so be it. |
according to this principle, it means a superclass can be replaced with a subclass... so it doesn't violate this principle as we are adding variables to the subclass or overriding them obviously if you then break your program by adding the wrong variable that's your fault, no amount of child stabalisers is gonna stop that person falling off his bike... in fact you can already over-ride a function and break your "Liskov substitution principle" then i'd like this to be a feature as it works in all other dynamic languages i've used... it's beginner freindly syntax which is the way GDScript should be... i understand some coders like to put all their vars in init because they get fed up with inconsistency so many purists want to pipe in and say it shouldn't be the case |
Describe the project you are working on
Test project
Describe the problem or limitation you are having in your project
Lets assume there is base class with a variable value and some logic that utilize this variable.
If try to extends this class with another with type hinted value like this:
or
it will brings an error:
The member "value" already exists in a parent class.
So the goal is to use already existed logic from BaseClass (that manipulate with var value) in another inherited classes but with type hinting that restrict to use distinct var type for particular inherited class.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Allow to override variables without type hinting from parent class with hinting some type in inherited classes.
Or add some ability to explictly specify variables type in inherited classes.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
For example:
Variant 1 - just allow to override variables.
Variant 2 - allow to specify variables type:
Variant 3 - allow to specify variables type with additional syntax:
Variant 4 - allow to override variables with additional syntax:
If this enhancement will not be used often, can it be worked around with a few lines of script?
I don't see a way to do this with class inheriting.
Is there a reason why this should be core and not an add-on in the asset library?
This is about improving GDScript
The text was updated successfully, but these errors were encountered: