Search code examples
typescripttypescript1.8

Why is changing protected access in a base class to public access in a derived class allowed?


In TypeScript this is legal code:

class Animal {
    name: string;

    constructor(theName: string) {
         this.name = theName;
    }

    protected move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

class Snake extends Animal {
    constructor(name: string) {
         super(name);
    }

    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters);
    }
}

class Horse extends Animal {
    constructor(name: string) {
         super(name);
    }

    move(distanceInMeters = 45) {
        console.log("Galloping...");
        super.move(distanceInMeters);
    }
}

However this would be illegal in C#, for example. Going from public to protected is not allowed in TypeScript, however.

What is the rationale for allowing a protected function to be exposed as a public function in a derived class? Coming from C# and Java, it doesn't make sense to me to allow the access level of a member to be changed at all.


Solution

  • What is the rationale for allowing a protected function to be exposed as a public function in a derived class

    It is allowed because its not disallowed. You are simply getting what you write (and since you didn't write the child became public as that is the default).

    More

    Language Design https://blogs.msdn.microsoft.com/ericgu/2004/01/12/minus-100-points/

    Going from public to protected is not allowed in TypeScript, however.

    For good reason. Consider the following 🌹

    class Animal {
        name: string;
    
        constructor(theName: string) {
             this.name = theName;
        }
    
        move(distanceInMeters: number = 0) {
            console.log(`${this.name} moved ${distanceInMeters}m.`);
        }
    }
    
    class Snake extends Animal {
        constructor(name: string) {
             super(name);
        }
    
        protected move(distanceInMeters = 5) { // If allowed 
            console.log("Slithering...");
            super.move(distanceInMeters);
        }
    }
    
    let snake = new Snake('slitherin');
    snake.move(); // ERROR 
    let foo: Animal = snake; 
    foo.move(); // HAHA made my way around the error!