Private class fields - #247
Conversation
|
Honestly, this is so much better than the previous RFC, but still some problem points:
Consider this example: open class Point
private _x: number
private _y: number
function __eq(self: Point, other)
return self._x == other._x and self._y == other._y
end
end
class ThreeDPoint extends Point
private _z: number
endThis should normally fail. Classes are already opt-in to inheritance, so we can use open class Point
protected x: number
protected y: number
function __eq(self: Point, other)
return self.x == other.x and self.y == other.y
end
end
class ThreeDPoint extends Point
private _z: number
end
class Vector
x: number
y: number
endWe assume these properties are all This could perhaps be solved with a parse-error: class Vector -- Error: Must explicitly define every field with an access specifier
x: number
y: number
private z: number
end
open class Base
private x: number
function compare(self, other)
return self.x == other.x
end
end
class Derived extends Base
public x: number
end
local a = Base.new(...)
local b = Derived.new(...)
-- We can know that this will compare Base.x to Derived.x.
local res = a:compare(b)In this case, we can know that |
|
Thank your feedback! I will do my best to address all your points, but please let me know if I miss any!
|
You can achieve the same exact system using It also allows the derived class to gain control over every one of its fields, which is what should be. Adding hidden fields will confuse users, and will create weird scenarios just like the one we're trying to solve in this RFC. |
Yeah I don't mind this to be honest. Maybe some folks who like POD-classes may disagree, and perhaps a solution like in the fork I've mentioned can be made, but for now a restriction seems fine. |
This proposal works nearly identically to how it works in C++, Java, and everything that's flowed from that. If private fields weren't available (but hidden) in derived classes, inheritance wouldn't even work for any class that has a private field. open class BasePoint
private _x: number
private _y: number
function __init(self, x, y) ... end
function length(self)
return math.sqrt(self._x * self._x + self._y * self._y)
end
end
class NamedPoint extends BasePoint
public name: string
function __init(self, x, y, name) ... end
end
local np = NamedPoint.new(..)
print(np:length()) -- how could this work if np didn't have _x or _y? |
With Personally, I don't complicate things by wanting to create a hidden field, to me, it is a worthless workaround for the fragile base class problem. In almost all of the cases I desired to use a hidden field, I only saw people (especially in Roblox codebases!) to find workarounds to continue violating it anyway. |
I agree with Noctua here. I also believe that instances of a class containing the private fields of the parent class is a bad idea when |
what does 'simply supporting composition' mean to you? |
Allowing class fields that are instances/objects of other classes and not supporting inheritance? |
I misinterpreted what was going on in this RFC and thought |
With what you are saying, wouldn't this mean that private fields would only be allowed to be accessed through private methods (if the method wasn't private, then it would be inherited by derived classes, except those derived class instances do not contain the private base class fields, hence error)? Also, what you are suggesting goes against the principle of encapsulation. Developers already use encapsulation in Lua with closures, so this is not anything new. Derived classes should not be able to manipulate data that is private to their base classes (because it creates opportunities for a derived class to interfere with its base class private fields in a way that the base class cannot anticipate). Base classes can offer methods to interface with its own private data and control the terms of the interaction. |
Any field you'd need to use in that case would just be protected. Or you wouldn't make it
A better argument would be to say that this behavior is quite the norm in many languages, and developers would expect to see it in Luau in one way or form. I propose it isn't necessary to make |
|
This PR introduces private fields for classes as a PR against the mega RFC (#242).
We introduce a different syntax than the last private field PR, emphasize the issues with having just a
privatekeyword, and de-emphasize performance/implementation considerations.Enjoy!