Start learning free

LESSON 558 OF 569 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Employees and Managers in JavaScript: Inheritance

Practice O(1) Read the full explanation

A company pays every employee a salary. A manager is an employee too, but earns a bonus on top of the salary. Write the two classes so that a manager reuses everything an employee has, and changes only how its pay is worked out.

Implement the class Employee:

  • Employee(name, salary) creates an employee. The name and the salary are private to Employee.
  • pay() returns the salary.
  • describe() returns the text <name> earns <pay>, where the amount is what pay() returns, for example Ana earns 3000.

and the class Manager, which inherits from Employee:

  • Manager(name, salary, bonus) lets the parent's constructor store the name and the salary, and stores the bonus itself, private to Manager.
  • pay() returns the parent's pay() plus the bonus. Call the parent's version, as in the lesson Calling the Parent Method: the salary is private to Employee, and the parent's pay() is what knows how an employee is paid.
  • describe() is not written again: Manager inherits it unchanged. Because describe() calls pay(), a manager's description shows the manager's pay, bonus included.

The input is a list of people, one per line: employee name salary or manager name salary bonus. For each line, the code that tests your classes creates that object and prints what its describe() returns, on a line of its own. The starter code spells these names the way your language does.

 

Example 1:

Input:
    employee Ana 3000
    manager Bob 4000 1000
Output:
    Ana earns 3000
    Bob earns 5000
Explanation:
Ana's pay is her salary. Bob's pay is the parent's pay, his salary 4000, plus his bonus 1000.
Bob's describe() is Employee's describe(), but the pay() it calls is Manager's.

Example 2:

Input:
    manager Cleo 5000 0
    employee Dan 5000
Output:
    Cleo earns 5000
    Dan earns 5000
Explanation: A manager whose bonus is 0 earns exactly the salary, like an employee.

Example 3:

Input:
    manager Eve 7000 2500
    employee Finn 2800
    employee Gus 3100
    manager Hana 6000 500
Output:
    Eve earns 9500
    Finn earns 2800
    Gus earns 3100
    Hana earns 6500
Explanation: Employees and managers come in any order, and each object keeps its own name and numbers.

 

Constraints:

  • 0 <= salary <= 106
  • 0 <= bonus <= 106
  • A name is one word of 1 to 20 English letters. Two people may have the same name.
  • At most 100 people per test case.
STEP 1 OF 9
    Ctrl + Enter to check

    JAVASCRIPT · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Employees And Managers in JavaScript, explained

    Problem overview

    A company pays every employee a salary. A manager is an employee too, but earns a bonus on top. The task is to write two classes so that Manager reuses everything Employee has and changes only how its pay is worked out.

    • Employee(name, salary) keeps the name and the salary in private fields. pay() returns the salary. describe() returns the text <name> earns <pay>, such as Ana earns 3000.
    • Manager(name, salary, bonus) extends Employee. The parent's constructor stores the name and the salary, and the manager stores the bonus in its own private field. Its pay() returns the parent's pay plus the bonus. It does not write describe() again.

    An employee Ana with salary 3000 describes herself as Ana earns 3000. A manager Bob with salary 4000 and bonus 1000 describes himself as Bob earns 5000, even though describe() is Employee's code.

    Approach

    describe() must not read the salary field directly. It calls this.pay(). When the object is an Employee, that runs Employee's pay. When the object is a Manager, this.pay() finds the manager's own version first, so the bonus shows up without any second describe. One method written once works for both classes.

    The private fields shape the rest. A #salary declared in Employee can be used only by code inside Employee, not by Manager. So Manager gets the salary the only way it can: by calling the parent's pay() with super.pay().

    Step by step

    1. Private fields of Employee. Declare #name and #salary inside the class body.
    2. Constructor. Assign the parameters to this.#name and this.#salary, so each object has its own values.
    3. pay(). For an employee, return this.#salary.
    4. describe(). Return the name, then " earns ", then this.pay(), joined with +. A number added to a string with + becomes text. Write this.pay(), not this.#salary.
    5. Manager. Write class Manager extends Employee, and declare its own private #bonus.
    6. Manager's constructor. Call super(name, salary) first. It runs the parent's constructor, which fills in #name and #salary. In a derived class, JavaScript requires this call before the constructor uses this.
    7. Store the bonus in this.#bonus, after super(...).
    8. Manager's pay(). Return super.pay() + this.#bonus.

    The solution in JavaScript

    class Employee {
        #name;
        #salary;
    
        constructor(name, salary) {
            this.#name = name;
            this.#salary = salary;
        }
    
        pay() {
            return this.#salary;
        }
    
        describe() {
            return this.#name + " earns " + this.pay();
        }
    }
    
    class Manager extends Employee {
        #bonus;
    
        constructor(name, salary, bonus) {
            super(name, salary);
            this.#bonus = bonus;
        }
    
        pay() {
            return super.pay() + this.#bonus;
        }
    }
    

    Using the classes

    const people = [
        new Employee("Ana", 3000),
        new Manager("Bob", 4000, 1000),
        new Manager("Cleo", 5000, 0),
        new Employee("Dan", 5000),
        new Manager("Eve", 7000, 2500),
        new Employee("Finn", 2800),
        new Manager("Hana", 6000, 500),
    ];
    for (const p of people) {
        console.log(p.describe());
    }
    

    This prints:

    Ana earns 3000
    Bob earns 5000
    Cleo earns 5000
    Dan earns 5000
    Eve earns 9500
    Finn earns 2800
    Hana earns 6500
    

    Cleo's bonus is 0, so she earns exactly her salary, like Dan. For a manager, pay() returns the salary plus the bonus, and m instanceof Employee is true: a manager is an employee.

    Why super.pay()

    Inside Manager.pay, this.pay() would be the same method calling itself, again and again until JavaScript stops it with RangeError: Maximum call stack size exceeded. super.pay() asks for the parent's version, which returns the salary. It is also the right call for a second reason: the salary belongs to Employee, and Employee's pay() is the code that knows how an employee is paid. If that rule changes, Manager follows automatically.

    Common mistakes

    • Using this before super(...). In a derived class, touching this first fails with ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor.
    • Reading this.#salary in Manager. A private field can be used only inside the class that declares it, so the class body of Manager can't use #salary. Using it there is a SyntaxError, because the name is not declared in an enclosing class.
    • Calling this.pay() inside Manager's pay. This is the endless recursion described above.
    • Repeating describe() in Manager. It isn't needed. Because describe calls this.pay(), the inherited method already uses the manager's pay.
    • Skipping the parent's constructor. Without super(name, salary), the parent's fields are never set.

    Testing

    A few inputs worth trying:

    • The largest values in the constraints: new Manager("Zed", 1000000, 1000000).describe() returns Zed earns 2000000.
    • A salary of 0: new Employee("Zed", 0).describe() returns Zed earns 0.
    • Two managers with the same name: new Manager("Ann", 100, 50) describes itself as Ann earns 150 and new Manager("Ann", 200, 5) as Ann earns 205. Each object keeps its own numbers.

    What inheritance gives you here

    Manager has no describe method of its own. When describe() is called on a manager, JavaScript looks in Manager first, finds nothing, and continues to Employee, where it runs the method with this still pointing at the manager. That is why one definition serves both classes, and why the inner call this.pay() reaches Manager's pay.

    The private fields work the same way as in any class. #name and #salary exist on every manager, because the parent's constructor created them, but only code written inside Employee can use those names. The text of Manager can't, and that restriction is what pushes the design toward super.pay().

    Another way to build the text

    A template literal builds the same text without +:

    describe() {
        return `${this.#name} earns ${this.pay()}`;
    }
    

    With this version, new Employee("Ana", 3000).describe() returns Ana earns 3000 and new Manager("Bob", 4000, 1000).describe() returns Bob earns 5000, exactly like the solution above. Either way, the amount comes from this.pay(), never from a field, so the manager's bonus is included.

    When to inherit

    Inheritance fits when one class really is a kind of another: a manager is an employee, so it can be used anywhere an employee is expected, and it adds or changes only what is different. Here the difference is a single method and a single field. If the two classes shared nothing but a few lines of code, a helper function would be a better tool than a parent class.

    Keep going with JavaScript500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free