-
-
Notifications
You must be signed in to change notification settings - Fork 22k
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
Implement an explicit virtual method mark for GDScript #103859
base: master
Are you sure you want to change the base?
Implement an explicit virtual method mark for GDScript #103859
Conversation
1978f80
to
cef1635
Compare
This would be complete if the overriden methods were highlighted in a different color |
I don't think this is necessary, as we already have an icon that hints the current method has overridden one from the base class - a blue arrow at the left of the line (line gutter, iirc) |
I think having
I don't understand this. Won't compatibility break either way? GDScript (unfortunately) raises error on unrecognized annotations, so annotations are already not forward-compatible. How is it any different than a contextual keyword? Why does making it a keyword mean forced error? Why can't it just be a keyword that raises a warning by default? |
Being a key word means that If you set this to a key word, yep it's literally compatibility-breaking, but we don't like to see that, unless we have something that upgrades your codes to fit the new grammar, but who prefers that? What's more, all methods, as I've said, are born with ability to be overridden by subclasses, without explicit annotations. So if the annotation becomes the key word, this won't accord with the nature of GDScript. Being an annotation, however, doesn't break the nature as you can still do that, except that you will receive a warning which doesn't break runtime and compilation. Last, I don't think this breaks the forward-compatibility, since as I've said before, warnings DOES NOT break runtime and compilation. As long as users can still compile the scripts and run the game as expected, I think that's ok and enough. |
I will add this here, since the linked proposal doesn't seem to reflect this exact proposed implementation. If we are adding an explicit |
what about a method that overrides base virtual one without explicit |
cef1635
to
1e2346b
Compare
Ok, I found a situation where the gutter doesn't help while extends RefCounted
class A:
var _t=1
@virtual func _test() -> void:
_t=2
class B extends A:
@override func _test() -> void: # No gutter at the left side. Believe it or not.
pass Inner classes in the same script with one overriding the base method whose owner is also one of the inner classes will not have any gutter at the left side. In this case, |
Dunno about GDScript, but it's a common pattern in e.g. C# analyzers to do exactly this: requiring code be written a certain way, with warnings if it isn't,
You misunderstood what I said. I'm not saying this specific PR breaks BACKWARDS compatibility. Regardless of whether it's annotation or keyword, old code will run on the new version just fine. I'm saying annotations in general (in GDScript) are, like keywords, not FORWARD compatible -- meaning new code with an unrecognized new annotation/keyword won't run in older versions, it raises an error. This is different from e.g. Because of this, I'd argue the difference between annotations and keywords is not really a matter of warning vs error, they are basically the same, as in they work the same (so much so many keywords in Godot 3 became annotations in 4). What to me seems to be the main difference is more that most/all annotations refer to Godot-specific features (e.g. |
We've discussed the differences between keywords and annotations in the past, trying to find a universal criterion for whether a particular language construct should be a keyword or an annotation. Various options were proposed:
In the end, we couldn't find such a universal criterion, and decided to decide on a case-by-case basis. Some notes from the discussion are documented here. In this case, I would favor |
For those who want to know what's the difference between an abstract method (#67777) and a virtual method, I updated the top post and you can check it for better understanding to these two, especially for those who have never touched with or dug in much deeper in this field. |
Implements and closes godotengine/godot-proposals#1631
Relative PRs: #103768, #67777
GDScript is a language where all methods are born with overridability, which brings confusion when it comes to user-defined
_
-prefixed methods (private methods). This pr implements an explicit way to mark a method, in GDScript, defined by user as a virtual method that can be overridden by subclasses. All old-fashioned overriding behaviors will be warned by the editor to maintain the compatibility with previous versions.Why not making it a key word?
Honestly, making it a key word sounds better than turning it into an annotation. However, being a key word means forced checking and forced error if you don't follow the rule, which greatly breaks compatibility with previous versions of Godot. To maintain the compatibility at the most extent, annotation doesn't sound a disaster for old scripts, so I selected making it an annotation instead of a key word with an error.
Does it mean that we cannot directly override an method without this mark?
You can still do this, as long as you welcome warnings to live with you 😏
Is this conflict with PR #67777 that introduces
abstract
?No, since you cannot annotate an abstract method as virtual because it is born to be overridden; while virtual methods are ones that are optional to be overridden, which means that you can also omit overriding the method in subclasses. A virutal mark cannot be used for an abstract method.
Is there any difference between an abstract method and a virtual one?
An abstract method must be overridden in a subclass, with any kind of implementation inside the function body, while virtual methods (or we can say all custom methods defined in GDScript) are optional to be overridden in subclasses.
Methods are all overridable already, so isn't this pointless?
No, this is not a pointless pr. As said before, this is a pr that helps make overriding a method explicit. Especially if you have checked #103768, you may realize that
_
-prefixed methods will be confusing when it comes to whether it is virtual+private or private only. This mark clarifies this and separate them apart from each other.Preview and demo
If you mark
test()
as virtualNotice that you are also supposed to add
@override
to explicitly annotate that the method overrides the virtual base method. Otherwise, a warning will be thrown.