Skip to content

Suggestion: 'protected' modifier #1

Description

General proposal

protected modifier acts the same as private in terms of code generation and assignability, except that it is possible to access a protected 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 a private member with the same name as a base class's member.

Examples

classBase{protectedmyMember;}classDerivedextendsBase{foo(){returnthis.myMember;}// OK}varx=newDerived();console.log(x.myMember);// Error, cannot accessclassDerived2extendsBase{privatemyMember;// Error, cannot tighten visibilitypublicmyMember;// Error, cannot widen visibility}

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:

classBase{protectedx: string;}classDerivedextendsBase{foo(n: Base){// Not allowed: cannot reference protected member through base class referenceconsole.log(n.x);}}

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 as private 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:

classWidget{protectedinspector: WidgetInspector;}classSquareWidgetextendsWidget{// Use a more-specific 'inspector'protectedinspector: SquareWidgetInspector;}classCircleWidgetextendsWidget{// Initialize hereprotectedinspector: WidgetInspector=newWidgetInspector();}varw: Widget;varc: CircleWidget;w=c;// Allowed, or not?

If we took the verbatim "same declaration" rule from private, this assignment would be disallowed because w.inspector and c.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 a CirceWidget even if they both removed their extends clauses. This is not surprising if you're used to thinking about things structurally, but since many people seem to like the higher specificity of private 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:

interfaceWatWidget1extendsWidget,CircleWidget{}interfaceWatWidget2extendsWidget,SquareWidget{}varww1: WatWidget1;varww2: WatWidget2;ww1=newWidget();// Allowed or not?ww1=newCircleWidget();// Allowed or not?ww2=newWidget();// Allowed or not?ww2=newCircleWidget();// Allowed or not?ww1=ww2;ww2=ww1;

Can public properties be assigned to protected fields?

classPoint1{x: number}varp1: Point1={x: 3};// AllowedclassPoint2{privatex: number}varp2: Point2={x: 3};// DisallowedclassPoint3{protectedx: number}varp: Point3={x: 3};// Allowed or not?

This is sort of a yes-or-no thing tangentially related to the previous question.

Metadata

Metadata

Labels

CommittedThe team has roadmapped this issueSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions