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

private/public setters and getters (GDScript properties) #2979

Closed
dalexeev opened this issue Jul 11, 2021 · 4 comments
Closed

private/public setters and getters (GDScript properties) #2979

dalexeev opened this issue Jul 11, 2021 · 4 comments

Comments

@dalexeev
Copy link
Member

dalexeev commented Jul 11, 2021

Describe the project you are working on

Not related / any game

Describe the problem or limitation you are having in your project

This proposal is not about private/public members, but about the set and get properties added in "GDScript 2.0". There is a separate proposal #641 for private/public members. This proposal assumes that #641 will also be implemented.

In "GDScript 2.0" the behavior of getters and setters has changed - setget has been removed and set and get properties have been added. At the same time, the behavior became more predictable. Previously, calling a setter/getter depended on whether the variable was accessed from inside or outside the script. Inside the script, the my_var variable could be accessed in two ways: my_var and self.my_var (in the second case, the setter/getter was called).

This change is good, now there is no difference between my_var and self.my_var. But at the same time, the ability to use my_var differently inside and outside the script, which is useful in some cases, was lost. Now we need to use another variable for this.

# public
var my_var:
    get():
        return _my_var
    set(_value):
        assert(false)

# private
var _my_var:
    get():
        return _config.get_value("game", "my_var", 0)
    set(value):
        _config.set_value("game", "my_var", value)

# private
var _config = ConfigFile.new()

Overall, this is good. But at the same time, instead of one entity, there are two. It takes up more space and wastes developer mind. Someone even suggested adding the ability to switch the behavior to the old mode (for specific variables). But I think I came up with a better solution.

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

I suggest adding the ability to specify access modifiers for set and get properties:

public var my_var:
    get():
        return config.get_value("game", "my_var", 0)
    public set(_value):
        assert(false)
    private set(value):
        config.set_value("game", "my_var", value)

private var config = ConfigFile.new()

For public variables, set and get properties set both public and private setters and getters, for private variables, set and get work like private set and private get. It is possible to specify both a public and a private setter/getter at the same time.

Note that this approach does not prohibit the use of the option with two variables, you can choose the behavior you want and be flexible enough to customize it. For example, you can set only a public setter and getter for a variable, and then in the script, when accessing the variable, the setter and getter will not be called.

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

I wrote above how it should look for the user.

I cannot say how this can be implemented. But the public set, private set, public get and private get properties should be understood as public_set, private_set, public_get, private_get, i.e. it is not function overloading, but different functions. If we add public/private for members, it is logical that public/private for properties will also be separated by a space.

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

No, this is about the GDScript syntax.

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

This cannot be done using an add-on.

@YuriSizov
Copy link
Contributor

I think it's a toss between personal takes if a backing field takes more of the developer's mind or if it eases it with obvious separation.

But practically speaking, I don't see this being implemented without general access modifiers being implemented. You still need a concept of access scope for this, so one would lead to the other.

Also making it work only here would confuse users and bring a lot of questions about it not working elsewhere.

@dalexeev
Copy link
Member Author

Also making it work only here would confuse users and bring a lot of questions about it not working elsewhere.

Are you talking about something like this:

public func f(): pass
private func f(): pass

?

I don't think there is a need for this elsewhere. Functions can only be called, constants can only be read, and only variables can be both read and written.

I don't see this being implemented without general access modifiers being implemented.

If I understood the essence of the claim correctly, then at the beginning I mentioned that this proposal implies that #641 will also be implemented.

Initially, I wanted to propose adding a different access modifier readonly (besides public, private, protected), so that access to the variable from the outside is limited to read only. But then I thought it would be better to make this system more flexible.

If you have two different entities - public and private, and you need to call the public setter from within the script, then this is one case. And if you have one public-private entity, and you just need to restrict write access from the outside, then this is a different case. It is logical not to produce entities unnecessarily.

Also, I'm a little tired of leading underscores. It's okay when they are used for private methods, but they are annoying in private variables. If #641 is implemented, then it will solve part of the problem, but this proposal will go further, eliminating the need to duplicate a variable in many cases.

@YuriSizov
Copy link
Contributor

If I understood the essence of the claim correctly, then at the beginning I mentioned that this proposal implies that #641 will also be implemented.

Ah, sorry, I read that completely the other way initially and considered this to be an independent proposal. In that case it's mostly about a toss between personal preferences to code organization. I personally don't think that a backing field is bad.

@dalexeev
Copy link
Member Author

dalexeev commented Feb 7, 2023

Closing due to lack of support.

I still find this an interesting concept, but it probably doesn't fit with the GDScript design. This is very similar to overloads, which most likely won't appear in GDScript due to its dynamic part and the goal of being simple.

The alternative mentioned above, although it is less flexible:

Initially, I wanted to propose adding a different access modifier readonly (besides public, private, protected), so that access to the variable from the outside is limited to read only. But then I thought it would be better to make this system more flexible.

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

2 participants