godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Access-control keywords/annotations `private` and `protected` for GDScript to avoid unexpected and/or unnecessary external access to current script #10779

Closed Lazy-Rabbit-2001 closed 1 month ago

Lazy-Rabbit-2001 commented 1 month ago

Describe the project you are working on

Coding with GDScript

Describe the problem or limitation you are having in your project

Currently, we can use a variable whose identifier begins with an underline _ to make it hidden from the document, and make it as if it were private or protected. However, for external access, e.g. accessing the _-modified variables/functions from other scripts, this does not prevent it from being accessed; instead, this is regarded as a "valid" access. This imbalance between its behavior in documentation and in the cross-script access does not, personally, match the general understanding for experienced programmers, especially those who expert in the languages with access limiters like private and protected, and would mislead a freshman that all properties in GDScript are accessible as he/she wishes, which is not beneficial for these freshman to get the correct acquirement of "safe access". Meanwhile, the lack of access limiter in GDScript is really a trick when it comes to whether it is a virtual function that can be driven by other objects, or merely a private/protected method that you cannot get access to from external scripts (that does not inherit the class that is going to be accessed to).

func _my_func() -> void: # Virtual
    pass # Will be called by other scripts because this should be driven by external scripts

func _my_func() -> void: # Private or protected
    pass # Should not be called by other scripts (that does not inherit this class, if protected)

However, as said before, if you are trying to force yourself to call the second _my_func(), the engine will not trigger any error, but this would lead your project into a mess and unsafety because of this unguaranteed access to the script, which would be more unsafe and worse when it comes to a teamwork where members does little on commenting their codes.

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

Introduce private and protected keywords, or @private and @protected annotations, to enhance the access safety of each GDScript.

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

By default, if no any one of these keywords/annotations gets used as a prefix of some variable/function, the variable/function remains public to all GDScripts, and can be accessed by external scripts. However, if any one of these gets applied as the prefix of a member/method, the member/method will be limited on being accessed to: private/@private modified: The member/method can only be accessed in inner environment, which means that only the other members/methods in the current script can access to this one. protected/@protected modified: The member/method can only be accessed in inner or inherited environment, which means that only the other members/methods in the current script or child-class script can access to this one.

For example (Here uses keywords as an example):

# Script A
private var a: int = 10
protected var b: int = 15

# Script B, where insA is the instance of the script A
insA.a = 20 # Error: Cannot access to an private member from external environment.
insA.b = 10 # Error: <The same, while the "private" should be replaced by "protected">

# Script C, inherting script A, where insA is the instance of the script A
insA.a = 20 # Error: Cannot access to an private member from external environment.
insA.b = 30 # Valid access and modification

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

An addon may achieve the similar function, however, this would be very tricky as the core components of GDScript language seems not to be exposed to GDScript, C# or GDExtension Cpp.

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

This should be a core feature as it may greatly enhance the safety of cross-script access. Meanwhile, an addon is hard to implement the similar function.

AThousandShips commented 1 month ago

Thank you for your proposal, consolidating in:

Please add any information that's not already been realised in that lengthy thread there