-
-
Notifications
You must be signed in to change notification settings - Fork 23.4k
Add abstract classes to GDScript #67777
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
Conversation
845d75c
to
f7f27ce
Compare
8daace1
to
36a62f0
Compare
36a62f0
to
3071b44
Compare
3071b44
to
74670c0
Compare
74670c0
to
955143a
Compare
Are abstract methods supported with this PR? |
@ryanabx No, only abstract classes are supported with this PR. |
955143a
to
2d4113e
Compare
2d4113e
to
b0390a3
Compare
|
Talked about in the current GDScript meeting. The PR should implement the elements 1 and 2 stated by @dalexeev. For number 3, we're still discussing this in the meeting, so no decision has been made. |
Yeah, my thoughts on 3. are whether it makes sense to (for this PR or eventually) have the "granularity" of abstractness exist at the class or at the method level. For example, with it at the method level: class AbstractBecauseOfAbstractMethods:
func this_method_is_implemented():
pass
@abstract
func this_method_is_virtual_slash_abstract()
func this_is_also_implemented():
pass
# ----------------------
class StillAbstract extends AbstractBecauseOfAbstractMethods:
func some_new_implemented_func():
pass
# ----------------------
class FinallyNotAbstractClass extends StillAbstract:
func this_method_is_virtual_slash_abstract():
pass We could force the users to annotate a class to be marked as abstract if any of its functions are still abstract. This would give people more granularity in what precisely makes the class abstract. It doesn't make GDScript any more expressive, since you can always 1) tag a class as abstract, then 2) have methods implemented with Folks agreed during the meeting that this wouldn't be a blocking thing for this PR, and that it could be implemented later :) |
I will get to work on 1. For 2, this is trivial because it's just removing |
Thanks! |
Been waiting for abstract classes, thanks! |
The age has seen this moment, and this should be one of the most milestone in gd 4.5. |
Changing the token enum values requires bumping the bytecode version. |
BIG W! Thank you!!! |
I have a question: so obviously you can't instantiate an abstract class using For example,
Because it seems like that would be an important thing to be able to do. Although, now I think of it, I wonder if some new keyword or other would be needed to make the constructor useful, since you'd need the function to return an object of the child class in the first place. Would calling I don't know; just thinking out loud. |
You can try it yourself to see if But since a constructor in an abstract class is usually operated to provide a basic and default initialization for its derived classes, I don't think there will be other use cases for the constructor of an abstract class |
Is there a way to define a abstract class without defining a global |
@IceflowRE So as an example you'd still mark the class as abstract in @abstract
extends Node
func some_func():
pass then in extends "my_abstract_class.gd" And then the one catch being that you need to preload the classes in order to use language features like the const MyAbstractClass = preload("my_abstract_class.gd")
const MyClass = preload("my_class.gd")
func test():
var some_object = MyScript.new()
if some_object is MyAbstractClass:
print("some_object is a MyAbstractClass")
some_object.some_func() Something like that, I haven't actually checked or tested it but that's what I gather would be the workflow for not using Quick Edit: using the |
there wont be |
@azur-wolve That's not a part of this pull request. This pull request only implements abstract classes. Other features like those you mention can be done in another PR. |
See |
This is all fairly critically worded, but by no means is it intended to criticize anyone who has been involved in this PR or the proposal or the discussion here or anything of that nature: it is purely added in regards to the exact keyword used to achieve the results, and is hopefully more helpful than not to future work/discussions. So on with it... I know this is already merged and closed, but wasn't sure where to put this: I completely agree with @HolonProduction (quoted) on this. There is another discussion going on in the gdscript chat, and I wanted to reiterate that It worries me that GDScript seems to be migrating into a C++-like syntax, with all the complexities which that entails (such as virtual, override, abstract, etc.). Are we going to add At the same time, I don't think In addition to that, I saw someone ask if there would be an abstract variable potential? I don't really understand how that would be possible. A variable should always be concrete, even if its type is abstract: the actual value contained in the variable must always be a concrete value or null, else Godot could not construct it, after all. Variables should not be allowed to be abstract especially since the concept of abstraction only really applies to functions, in C++ and in most other languages I can think of. In GDScript, you can already achieve something similar using functions, since functions can be overridden. |
@WolfgangSenff See this proposal: godotengine/godot-proposals#11791 I agree that the name mismatch is unfortunate, so I propose to swap the C++ names, or pick new names to avoid confusion. GDScript isn't really "migrating into a C++-like syntax", more towards C# if anything. In C#, you can inherit abstract classes. |
If I were writing a GDScript class that I didn't want to be instantiated, I would expect the keyword I'd use to be |
that reminds to C# |
C# |
@OhiraKyou The question is what to call the thing the engine already does where those classes cannot be inherited or instantiated. |
@aaronfranke I know nothing about this or how "abstract" differs in C/C++ but... |
I think the current names are fine. Abstract classes in C++ (in Godot) cannot be instantiated, but they can be inherited -- in C++. That's their purpose - CanvasItem can't be instantiated, but it's inherited by Node2D and Control, which can be instantiated. Abstract classes in GDScript are similar, they cannot be instantiated but they can be inherited, and their derived classes can be instantiated, so everything is fine. |
See #107717 for a follow-up discussion about changing this back to an annotation. |
Implements and closes godotengine/godot-proposals#5641
This PR adds a keyword for marking a script class as abstract in GDScript.
I tested multiple combinations of abstract and non-abstract inheritance and they all work. As an example, in this image
MyAbstract
is@abstract
, while the other is not. Note that ifExtendsMyAbstract
was made abstract then both would be hidden.And here's what happens if you try to instance with
.new()
:A previous version of the PR used
@virtual
, but the feedback has been overwhelming thatabstract
is better. After that, another previous version of this PR used an annotation@abstract
, but it was discussed that a keyword is preferred, then discussed again in #107717 that an annotation is preferred.Production edit: closes godotengine/godot-roadmap#66