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

Other ways of declaring private fields #33

Closed
eddyw opened this issue Nov 20, 2017 · 5 comments
Closed

Other ways of declaring private fields #33

eddyw opened this issue Nov 20, 2017 · 5 comments

Comments

@eddyw
Copy link

eddyw commented Nov 20, 2017

I'm not sure if this is the best place to ask. Since I couldn't get a clear answer why other methods for declaring private fields where not considered in this thread tc39/proposal-class-fields#59
I would like to know if here somebody could clarify.

To sum up,
I read the FAQs and I get why the # chars was chosen. What I disagree with is the way private fields are declared.
In the discussion I mentioned the following example to be confusing:

class {
  $validField = 1
  _validField = 2
  #validField = 3 // This is private, but looks similar to the above
  method() {
    this.$validField
    this.#validField
  }

Here, there is nothing that makes the code self explanatory. $ and _ are still perfectly valid chars to define a variable.
What about:

class {
  $ = jQuery
  _ = lodash
  #$ = Other
}

I asked later in the thread, why isn't this syntax better?:

class {
  $validField = 0 // public
  _validField = 0 // public
  private #validField = 0 // code self explains it's a private var
  private #$validField = 0 // less confusing
  static private #_validField = 0

  method() {} // public
  $method() {} // public
  private #method() {} // private
  private #$method() {} // private
  static private #method() {} // private

  constructor () {
    this.#method() // they way of accessing doesn't change as proposed before
  }
}

Why?
Public fields are defined without the public keyword
Static fields are defined with the static keyword
Private fields are defined the same way public fields are with special chars _ and $ which makes it confusing and the code less self explanatory
By not using a keyword private, it may limit future proposals for other kinds of fields (protected, friend for instance. Would they need to come up with another unused character?)

Could somebody clarify if these points where taken into account? If so, does that mean defining vars beginning with _ and $ should be considered a bad practice in the future to avoid making the code not readable when working with private fields?

@littledan
Copy link
Member

We did discuss making a (technically) redundant private keyword which would come before the # in declarations to make it clear that this is private. The conclusion was to omit this, based on a principle from @dherman , that we should be coding the syntax in a way that would be learnable and usable by practitioners, but that we shouldn't force the syntax to say something repetitive and meaningless just to force them to repeatedly document how the language works.

The working theory of the proposal is that users will learn that # means private. Once you learn that, it would feel redundant and silly to also type the word private all over the place.

Many programmers have written in for bugs saying they'd prefer private fields declared with a private keyword. However, for most people with this concern, the issue is largely that they find # extremely ugly. For them, I don't think an additional private would ameliorate things.

@eddyw
Copy link
Author

eddyw commented Nov 21, 2017

Thanks for answering. It makes kind of sense and I'm also among the people who dislike the # char but I didn't want to start another tread about that.

What I actually dislike about that char is that is similar to $ and _ for declaring fields. Those are still perfectly valid chars for declaring variables.

I was going to suggest the following before:

class {
  static prop = 0
  private prop = 0
  prop = 0
  method() {
    new.target.prop // refers to static field
    new.self.prop // would refer to private field
    this.prop // would refer to own
  }
}
// Or
class {
  #prop = 0
  method() { new.#prop }
}

However, that leaves private static fields out. So, I will just accept it as it is.

I do have one question. A private static field cannot be accessed from an instance method of the same class, right?

class {
  static #prop = 0
  static method() {
    this.#prop
  }
  method() {
    new.target.#prop // < No?
    new.privateFields.#prop // < Or something like this alternatively
  }
}

Since new.target is only accessible when a new instance is created with new operator, would a Class be allowed to access its own private static fields? (At least in this way?). I mean, the static private field stills belongs to the class, even though an instance of it is created.

The point is, if a static private field can be shared between static and public fields within the same Class.

@eddyw
Copy link
Author

eddyw commented Nov 23, 2017

We did discuss making a (technically) redundant private keyword which would come before the # in declarations to make it clear that this is private.

Just curiosity. Because many people asked about protected fields (Private fields that can be shared between classes), could this proposal include them? That way, it won't be redundant adding a private keyword. For instance:

class A {
  static private #a = 0 
  static protected #b = 0
  private #a = 0
  protected #b = 0
  method() {
    this.#a
    this.#b
  }
}
// Other class
class B extends A {
  method() {
    this.#b // ok
    this.#a // throws
  }
}

@littledan
Copy link
Member

The intention of this proposal is to leave protected as a follow-on provided by decorators.

@littledan
Copy link
Member

Thanks for filing this issue. Please reopen if you see a problem with the current plan of sticking with the # syntax and providing protected through decorators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants