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 Object virtual _can_instance() for managing the ability to instantiate a class #1992

Closed
me2beats opened this issue Dec 16, 2020 · 5 comments

Comments

@me2beats
Copy link

Describe the project you are working on

Godot plugins

Describe the problem or limitation you are having in your project

For my plugins I use (often) Util classes, that shouldn't be instantiated and (sometimes) Singletons (not autoload ones) that should be instantiated only once.
The problem is the plugin user may not know that so .new() objects can be accidentally created by user which may be unexpected/dangerous.

But this is not only feature for plugin devs. I think everyone is interested in creating reliable foolproof scripts, which always requires setting lots of restrictions. And one of them is managing the possibility of creating class instances.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Ability to specify how many class "instances" can be created would solve the problem.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I think the most flexible way is to have Object virtual _can_instance() method.

bool _can_instance() virtual
Returns true if the script can be instanced.

This allows to flexiblly dynamically manage the ability to instantiate classes.

so when I created my Util class and I don't want it to be instantiated I could write:

extends Reference
class_name MyClass

func _can_instance():
    return false

So MyClass.new() would give error/warning like

MyClass shouldn't be instantiated

If this enhancement will not be used often, can it be worked around with a few lines of script?

it seems there's no good way to do this.
It's possible to override static new():

static func new():
    pass

but I really don't think this is a good idea, and also not flexible at all

Is there a reason why this should be core and not an add-on in the asset library?

See above. Hopefully this will make (Gd)scripts more reliable.

@willnationsdev
Copy link
Contributor

Rather than having a virtual method on the instance (since you'd have to first create an instance to be able to call the method in the first place), you'd likely want a static method on the Script itself.

extends Reference
class_name MyClass
static func is_static() -> bool:
   return true
   
# other_script.gd
func _init():
   if not MyClass.is_static(): # default impl returns false
       var x = MyClass.new() # safe
   else:
       var x = MyClass.new() # if do it anyway, returns `null`, logs error.

@me2beats
Copy link
Author

me2beats commented Jan 1, 2021

@willnationsdev this is a helpful note.
Yea I need similar behavior, and the main idea is that this check

if not MyClass.is_static()

should happen implicitly, automatically, as there is no guarantee that the user will always explicitly write this if not line

@dalexeev
Copy link
Member

If you want to create a static class (something like a singleton), then I think it should be a keyword/annotation (@static_class), not a virtual method.

Now, if you want to make sure that some class is not instantiated, you can use something like:

func _init():
    push_error("The class shouldn't be instantiated")
    breakpoint

@willnationsdev
Copy link
Contributor

@dalexeev Yeah, now that we're approaching 4.0, an annotation would be the more appropriate solution in GDScript.

@me2beats
Copy link
Author

me2beats commented May 1, 2022

ok closing now

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

5 participants