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

Add a keyword for abstract classes in GDScript #67777

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

aaronfranke
Copy link
Member

@aaronfranke aaronfranke commented Oct 23, 2022

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 if ExtendsMyAbstract was made abstract then both would be hidden.

Screen Shot 2022-10-23 at 1 41 22 PM

abstract class_name MyAbstract extends Node
class_name ExtendsMyAbstract extends MyAbstract

And here's what happens if you try to instance with .new():

Screen Shot 2022-10-23 at 3 12 40 PM

A previous version of the PR used @virtual, but the feedback has been overwhelming that abstract is better. After that, another previous version of this PR used an annotation @abstract, but it was discussed that a keyword is preferred.

Production edit: closes godotengine/godot-roadmap#66

@aaronfranke aaronfranke added this to the 4.0 milestone Oct 23, 2022
@aaronfranke aaronfranke requested review from a team as code owners October 23, 2022 02:27
@aaronfranke aaronfranke changed the title Add an annotation for virtual classes in GDScript Add an annotation for abstract classes in GDScript Oct 23, 2022
@aaronfranke aaronfranke force-pushed the virtually-annotated branch 3 times, most recently from 8daace1 to 36a62f0 Compare October 24, 2022 01:02
@aaronfranke aaronfranke modified the milestones: 4.0, 4.x Nov 6, 2022
core/object/script_language.h Outdated Show resolved Hide resolved
editor/create_dialog.cpp Outdated Show resolved Hide resolved
core/object/class_db.cpp Outdated Show resolved Hide resolved
@ryanabx
Copy link
Contributor

ryanabx commented Sep 4, 2023

Are abstract methods supported with this PR?

@aaronfranke
Copy link
Member Author

@ryanabx No, only abstract classes are supported with this PR.

@dalexeev
Copy link
Member

dalexeev commented Sep 4, 2023

  1. I think the @abstract annotation should be possible to apply not only to the top-level script, but also to inner classes. Applying the annotation to a script should not make inner classes abstract.
  2. The check should be performed in release builds too.
  3. Perhaps this should be keyword abstract (like static and potential public/private) rather than annotation @abstract, especially if we add the ability to declare methods abstract (must be implemented in a child class so that it can be non-abstract).

@adamscott adamscott requested a review from vnen September 4, 2023 13:40
@adamscott
Copy link
Member

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.

@anvilfolk
Copy link
Contributor

anvilfolk commented Sep 4, 2023

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 assert(false) or pass, which would be functionally the same.

Folks agreed during the meeting that this wouldn't be a blocking thing for this PR, and that it could be implemented later :)

@aaronfranke
Copy link
Member Author

I will get to work on 1. For 2, this is trivial because it's just removing #ifdef DEBUG_ENABLED. To be clear I don't mind it in release builds, I just wanted to exclude it for improved performance, but if it's desired then we can do that. For 3, I think an annotation makes more sense than a keyword.

@dalexeev
Copy link
Member

@aaronfranke For me, this is more of a language feature, since it prohibits instantiation of the class, and not only makes the class unselectable in the editor dialog. Especially if we add abstract methods later (#82987). That is, abstract is a common modifier for languages, the same as static and private. If we add this, then it makes sense for all three to be either keywords or annotations. I think we should look into the annotation vs keywords issue. See also godotengine/godot-proposals#5165 and godotengine/godot-proposals#6192.

@aaronfranke
Copy link
Member Author

aaronfranke commented Feb 22, 2024

@dalexeev I would say static is far more fundamental than abstract, as it drastically changes behavior, while @abstract and a potential @private only restrict behavior, preventing you from doing something.

This PR initially did not have @abstract used in release mode since it is mostly a tool for code organization, and you can just drop it to get the same behavior for code that ran correctly in the editor. I changed this due to feedback since then. But anyway, if you drop or add static, the behavior vastly changes and is mutually incompatible in both directions.

It does not make sense to me for static to be an annotation.

@salloom-domani
Copy link

To support @aaronfranke opinion, global abstract annotation indeed makes more sense than a keyword since it's kinda like @tool and more style consistent.
However, it will become an issue when abstract methods are implemented, because it has to be annotated for consistency reasons, even though a keyword better suits this case.

@aaronfranke
Copy link
Member Author

Yeah that's true, if the behavior is significantly different with abstract methods a keyword might make more sense.

@aaronfranke aaronfranke force-pushed the virtually-annotated branch 2 times, most recently from 0716b68 to f726965 Compare March 15, 2024 05:52
@@ -0,0 +1,2 @@
@abstract
class_name TestConstructAbstractScriptNotest

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test class look too simple for a real abstract class.

Only mark a class as abstract will not cover a typical abstract class.
An abstract class has typical full implemented functions and also abstract function you need to implement in the inheriting class.

What does an abstract function signature look like?

@abstract
class_name TestConstructAbstractScriptNotest extends Node:

func foo() -> String:
    return "foo"

# define a abstract function you need to implement by using the annotation
@abstract
func bar() ->String;

# or define a abstract function by using the key word
abstract func bar() ->String;

Copy link
Member Author

@aaronfranke aaronfranke Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR does not implement abstract functions, only abstract classes. See #82987

Copy link

@MikeSchulze MikeSchulze Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a there is a follow-up 👍

@micycle8778
Copy link

I'm confused on what we're waiting on for this to be merged. Are we just waiting for people on the gdscript team to review this? Is there something I can do to help?

@Calinou
Copy link
Member

Calinou commented Apr 9, 2024

I'm confused on what we're waiting on for this to be merged. Are we just waiting for people on the gdscript team to review this? Is there something I can do to help?

You can help get this PR merged by testing it locally and making it sure it works correctly (make sure to report results).

We can't guarantee this PR will be merged for 4.3 though, since it has the 4.x milestone.

@akien-mga
Copy link
Member

I'm confused on what we're waiting on for this to be merged. Are we just waiting for people on the gdscript team to review this? Is there something I can do to help?

There's ongoing discussion among GDScript contributors on whether this should be an annotation or a keyword. We'll update when a consensus is reached.

@dalexeev
Copy link
Member

At today's GDScript team meeting, we reached a consensus that abstract should be a keyword instead of an annotation.

@aaronfranke Please let us know if you would like to continue working on this and if you need any help. You can discuss implementation details on the #gdscript channel. Thanks for your patience!

@dalexeev dalexeev dismissed stale reviews from AThousandShips and themself April 23, 2024 15:17

Needs to be re-implemented as a keyword.

@aaronfranke aaronfranke changed the title Add an annotation for abstract classes in GDScript Add a keyword for abstract classes in GDScript Apr 27, 2024
@RadiantUwU
Copy link
Contributor

Can this be moved to the 4.4 milestone?

@RadiantUwU
Copy link
Contributor

Have had this PR in my fork for over a month, had no issues with it.

@HolonProduction
Copy link
Member

I don't think the name abstract is good, because it creates a confusion with native abstract classes which behave differently (e.g. can't be inherited), this will create confusion when talking about it or documenting stuff about it.

Could someone link me to the previous version were virtual was discarded?

Copy link
Contributor

@RadiantUwU RadiantUwU left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good to me, havent had issues with this PR at all inside my own fork.

@dalexeev dalexeev mentioned this pull request Oct 1, 2024
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for abstract classes in GDScript