Protected support for `class`

It's not a preference. It's the rule that exists in compiled class-based languages. Consider this. Suppose "A" was "Shape", "B" was "Box", "C" was "Circle", and "A::p" was the abstract function "RenderShape". If "B" could call "C::p", then the functions in B expecting the data of a quadrilateral would instead receive data for a circle. Bad deal. Sure the example is contrived, but the reality stays the same regardless.

Another way to think of it is that a "protected" member is a private member shared specifically with a selected descendant. The shared element is therefore "effectively private" to that descendant as well as sharable to further generations. So despite the common ancestor, the shared protected member is private with respect to the inheriting class. There should be no means for another class to see that data despite inheriting the same members from the ancestor.

I'd love to see this become natively implemented. I'm fairly certain a lot of other developers would as well.

Makes sense, that could cause a problem. I agree, this may be better. This case is covered by either of my two options anyways.

I think it'd be interesting to have the ability to specify differing levels of protectedness somehow, which would allow communication across sibling classes, but still keep things hidden from public. Do any languages have that?

It's making me want to get the Firefox source and give it a try.

I know I'm way late in replying, but I've been thinking about @ljharb and his objections toward "protected" being added. I'll get to that in just sec.

That's precisely the standard approach to the class keyword used by most compiled languages.

  • private: accessible only to member functions of the declared class.
  • protected: accessible to member functions of the declared and descendant classes.
  • public: accessible to any function via the instance object.

In more recent languages, there's also something similar to...

  • internal: accessible to all functions within the same compiled module via the instance object.

@ljharb

Over the years that I've known your stance on this issue, you've been fond of saying something like this:

That's a direct quote, but you've said something similar many times. My question to you is whether or not that stance is unassailable. As you know, I believe it to be flawed with as strong a conviction as you believe it to be sound. I now have a potential way of showing you that flaw. Hopefully you'll humor me and discuss this. I'll begin here:

Your statement above implies that the "visibility" in ES is not reasonably similar to "access levels" provided by compiled languages (and other languages supporting both "class" and "protected". I find fault for 3 main reasons:

  1. While ES does indeed only support 2 levels of visibility, those visibility levels are specific to a function environment. Put simply, just because a function has access to certain data available via a certain object during a certain run of that function, does not mean that on subsequent runs of that function, the same access will be afforded. It also does not imply that other functions declared within the same scope will have that same access. This implies that the visibility you mention is already conditional. It's not simply a matter of whether something is visible or not from this point in the code, but rather whether or not it is visible from this point in the code on this run with these parameters and this environment configuration. The existence of conditional visibility is the core feature required to create a "protected" visibility.
  2. The existence of a "protected" visibility does not change the truth that given the constraints mentioned above, a member of an object will either be accessible or not. The simple fact that "protected" can be emulated in a secure fashion that would even meet with your requirements (should you allow for such thing) is by itself proof that the language can support such a concept without breaking the existing all-or-nothing visibility constraint of ES.
  3. The concept of "accessibility levels" (as I desire it implemented, at least) is not at all incompatible with "visibility", but rather a recognition that "visibility" is already conditional in ES. Taking advantage of that conditional nature is the core method for producing the "protected" functionality desired.

You mentioned before that such is not seen often in the wild. That's true. It's likely you've almost never seen it, but that is also for good reasons.

  • The abstraction is complicated to implement properly in ES.
  • There is nothing even remotely ergonomic about such an implementation.
  • Most developers do most of their development work for a company that is not likely to approve non-standard, not well-known, not major company backed libraries, even if they provide a reasonable benefit to the productivity of a developer.

There's more reasons, but those are the top 3 that I can think of. Despite this, you can already see from the traffic in the GitHub repo that there is a desire to also have "protected" visibility within class. The absence of this feature constrains the usability of class to the point that the arguments against it made by those who don't see it's utility are indeed correct. There is scarce little that provides any unique benefit to using class. Compound this with the array of footguns packed into the current "private fields" proposal and the unfortunate reality is that class does not provide the power and flexibility required by those who would otherwise take full advantage of it.

1 Like

JavaScript already supports this feature:

class MyClass {
    get field() { return undefined; }
    constructor(value) {
       super.field = value;
    }
    method() {
       super.field *= 5;
    }
    log() {
        // still accessible from within the class
        console.log(super.field);
    }
}

(Unfortunately, V8 optimizes this pattern poorly.)

I wish. Your super.field exists on the prototype. You just modified the prototype of all instances of MyClass. That is by no means the same as what protected grants you.

Hi, the ECMAScript 2022 brought support for private methods and properties using #. But still without protected support. I think that now is a good moment to implement it.