-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Suggestion: 'protected' modifier #1
Comments
Great edit history on this one. We should discuss this. |
👍 |
1 similar comment
👍 |
+1 |
+1 👍 , I just started with typescript, and protected visibility is a really big missing feature when you are creating an OO API. |
@RyanCavanaugh Saw your tweet asking for feedback! Here are some thoughts:
No. Aside from the other existing arguments, this doesn’t match what I expect I think this is an easy and safe way to go since if it’s absolutely necessary to access the other object’s protected properties for some reason without a compiler warning, there is still a way to get around it (
In the first example, I would expect Given the degenerate example, CircleWidget extends from Widget already so this declaration is effectively
No. This goes back to the whole “only touch your own things” thing. I think it makes it easier to think of how you’d use properties like this if you were writing vanilla JS—they’d typically be underscored to annotate “protected”, and assignment to these properties from outside the constructor/prototype methods would typically be an illegal operation. Hope that helps! |
@csnover 👍 |
Oh, one other thought, since it was brought up above and so is I guess related—I don’t feel like private properties of an object should be considered in whether or not a type assignment is compatible, although I realise (only just) that they are right now. Only the public properties are what I would expect to be compared in assignment or passing, not private, not protected. I would only consider private/protected types in the inheritance system. |
This isn't a good idea because assignability is what determines parameter validation, for example class MyPoint {
private _length;
constructor(public x: number, public y: number) {
this._length = Math.sqrt(x * x + y * y);
}
differenceInLength(p: MyPoint) {
return p._length - this._length;
}
}
var regularPoint = { x: 3, y: 6 };
var myPoint = new MyPoint(10, 10);
// Desired: Error
console.log(myPoint.differenceInLength(regularPoint)); // No error, prints NaN |
I realize this is probably already set in stone and I apologize for digging up a bones, but I wanted some clarifications on the decision that was made for "Is 'sibling' property access allowed?" To me, it makes sense that siblings can use each other's protected methods if the protected method is defined in a common parent (super) class. In effect, I view protected methods as creating an interface (as opposed to defining an implementation detail) that can be viewed by ______ (the blank space is specific to the language, in TypeScript's case, it would be the inheritance chain). In effect, this is how I think about it: The sub classes know that they have to implement the interface defined by the super class. Similarly, they know that all their siblings have to do the same in order to be an instance of the parent class. They can see the protected method from their parent, so it must exist on the siblings. Since these classes know this, it doesn't seem like its breaking encapsulation by allowing siblings to access protected methods. I place emphasis to indicate that the protected method is not optional and that it is a known fact by all siblings that it exists. This is different than private methods in which case the existence of the methods are unknown and therefore unusable outside the class. I ask because I'm designing some classes using a composite pattern. One of the protected methods for the composite object is supposed to iterate over the objects it contains and return a composite value. The method is defined as protected in the super class and therefore known to exist by the composite object. Obviously I could easily make the method public, but following the principle of least privilege, it makes sense to make it protected since this method is only used within the inheritance chain. |
General proposal
protected
modifier acts the same asprivate
in terms of code generation and assignability, except that it is possible to access aprotected
member in any subclass of a class which declared the member. Basically, you can access protected members in the same situations where it would have been an error for you to redeclare aprivate
member with the same name as a base class's member.Examples
Open Questions
After the last design meeting, the following open questions remained:
Is 'sibling' property access allowed?
C# and other IL languages prohibit this pattern, but Java allows it:
See these links for reasoning
http://blogs.msdn.com/b/ericlippert/archive/2008/03/28/why-can-t-i-access-a-protected-member-from-a-derived-class-part-two-why-can-i.aspx
http://stackoverflow.com/questions/1904782/whats-the-real-reason-for-preventing-protected-member-access
Are
protected
members subject to the "same-declaration" rule asprivate
members for assignability/subtyping?private
members are considered equivalent for the purposes of assignability and subtyping if they are from the "same declaration". This isn't quite the rule you would want for protected members. Consider some classes:If we took the verbatim "same declaration" rule from
private
, this assignment would be disallowed becausew.inspector
andc.inspector
come from different declarations. It's not reasonable to have this assignment be disallowed.However, if we do not use the "same declaration" rule, then a
SquareWidget
would be assignable to aCirceWidget
even if they both removed theirextends
clauses. This is not surprising if you're used to thinking about things structurally, but since many people seem to like the higher specificity ofprivate
in terms of preventing assignability between structurally-equivalent types, this behavior might not be desirable.A proposed rule was that we could have a notion of a "parent" declaration when a derived class's property overrides a base class property. This seems tractable for classes, but interfaces can
extend
multiple classes, and we would need to define what exactly that means. A degenerate example:Can public properties be assigned to protected fields?
This is sort of a yes-or-no thing tangentially related to the previous question.
The text was updated successfully, but these errors were encountered: