RFC for private class fields - #241
Conversation
|
Considering class Point
public x: number
public y: number
local #cachedLength: number?
-- etc
end |
|
This design doesn't work in conjunction with inheritance. If we consider the example of open class Base
local #foo: number
function #__init(self)
self.foo = 1
end
function getBaseFoo(self)
return self.#foo
end
end
class Sub extends Base
local #foo: number
function __init(self)
self.#foo = 2
end
function getBothFoos(self)
return self.#foo, self:getBaseFoo()
end
end
NB I know protected function setBaseFoo(self, val)
self.#foo = val
endto allow subclasses to control |
|
Let's talk about the syntax. The "local" and "#" being used to declare public or private fields is completely awful. The RFC proposes them as an alternative to a potential ambiguity issue with actual access specifiers. First of all, what does even "local" mean in the context of classes? Are they local variables? Or fields? Are they the same as our normal local? Will the user be able to differentiate between them? And the "#" symbol used for private fields is horrible, especially combined with the "local", it looks like I'm trying to get the length of a variable, rather than declaring a private field. This syntax is confusing, hard to read, and provides little to no benefit other than resolving an ambiguity issue, which I believe could be resolved with other means. That aside, the problem of private constructors becoming difficult to implement have arisen immediately after reserving |
|
Using the length operator for identifying a field as private is for lack of a better word "crazy". Especially there is a |
| end | ||
|
|
||
| function getMagnitude(self) | ||
| return self:#computeMagnitude() |
There was a problem hiding this comment.
i think :#method() looks grotesque and almost serves as a drawback to this counterexample on its own. consider:
return self:
#computeMagnitudeeven without whitespace, it looks far too similar to e.g. #arr, and feels wildly inconsistent. i'm sympathetic to the issues which might come from keywords but i feel like this syntax needs some work
| local a = Base.new(...) | ||
| local b = Derived.new(...) | ||
|
|
||
| -- Should this compare Base.x to Base.x, or Base.x to Derived.x? |
There was a problem hiding this comment.
should this even be allowed? i feel like having two values for x in and of itself is a pretty large footgun, even with an access modifier for the private one
There was a problem hiding this comment.
Unfortunately, the equivalent of this is legal in other languages. If we were to raise some sort of error on public x in Derived shadowing private x in Base, this worsens the fragile base class problem where the author of Base is now restricted in what private property names they can use without causing errors downstream.
There was a problem hiding this comment.
i'm definitely sympathetic to fragile base class problems, but I'm not sure the end justifies the means here. Is it really a solution if the result which we're making possible is confusing to read anyways? Admittedly it could just be a lint, but I'd personally prefer that kind of ambiguity just yell at people. Rename symbol exists for stuff like this
There was a problem hiding this comment.
Unfortunately, the equivalent of this is legal in other languages. If we were to raise some sort of error on
public xinDerivedshadowingprivate xinBase, this worsens the fragile base class problem where the author ofBaseis now restricted in what private property names they can use without causing errors downstream.
The fragile Base class problem is an issue that you mostly cannot resolve on your own. I would prefer a ban rather than having a solution which is incredibly hard to work with.
Apologies if the framing of the RFC made it seem like the glyph approach was chosen for performance reasons. Our main concern was the semantic ambiguity that falls out of allowing child classes to shadow private fields in their parents with their own public fields. That being said, we understand the concern around the particular glyphs and keywords we chose, and are happy to discuss alternatives in this space! |
|
In terms of that ambiguity, is that something that ever actually pops up? At least from personal experience I don't think I've ever found it to be a problem in other languages? There's also the consideration that editors can syntax highlight privates differently to publics which brings back the "easy way to tell if it's public or private when reading code" part. |
Updated the reply to be more clear, sorry about that! |
Also introduce the `open` keyword to allow classes to explicitly opt into inheritance.
* tweak __eq rule * tweaks
20d61f2 to
466dae2
Compare
|
Closed in favor of #247 |
Rendered
Enjoy!