Next: , Previous: Type Checks and Polymorphism, Up: Inheritance


2.2.6 Visibility Escalation

Let a\_n denote a numeric level of visibility for dfn\_n\^C such that the access modifiers (see Access Modifiers) private, protected and public are associated with the values 1, 2 and 3 respectively. Let a' represent a in regards to C' (see Inheritance).

For any member n of dfn, the following must be true:

2.2.6.1 Discussion

Visibility escalation is the act of increasing the visibility of a member. Since private members cannot be inherited, this would then imply that the only act to be considered "escallation" would be increasing the level of visibility from protected to private.

Many follow the convention of prefixing private members with an underscore but leaving omitting such a prefix from protected members. This is to permit visibility escalation without renaming the member. Alternatively, a new member can be defined without the prefix that will simply call the overridden member (although this would then not be considered an escalation, since the member name varies).

In order to increase the visibility, you must override the member; you cannot simply redeclare it, leaving the parent definition in tact. For properties, this has no discernible effect unless the value changes, as you are simply redefining it. For methods, this means that you are overriding the entire value. Therefore, you will either have to provide an alternate implementation or call ‘this.__super()’ to invoke the original method.

Note that you cannot de-escalate from public to protected; this will result in an error. This ensures that once a class defines an API, subclasses cannot alter it. That API must be forever for all subtypes to ensure that it remains polymorphic.

Let's take a look at an example.

    var Foo = Class(
        {
            'virtual protected canEscalate': 'baz',

            'virtual protected escalateMe': function( arg )
            {
                console.log( 'In escalateMe' );
            },

            'virtual public cannotMakeProtected': function()
            {
            }
        } ),

        SubFoo = Foo.extend(
        {
            /**
             * Escalating a property means redefining it
             */
            'public canEscalate': 'baz',

            /**
             * We can go protected -> public
             */
            'public escalateMe': function( arg )
            {
                // simply call the parent method
                this.__super( arg );
            }
        } );

Figure 2.17: Visibility can be escalated

Note that, in the above example, making the public cannotMakeProtected method protected would throw an error.