Start learning free

LESSON 563 OF 574 · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

Employees And Managers in Swift: Inheritance and override

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

    SWIFT · OBJECT-ORIENTED PROGRAMMING - CHALLENGES

    Employees And Managers in Swift, explained

    Problem overview

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

    Employee has:

    • an initializer Employee(name, salary); the name and the salary are private to Employee;
    • pay(), which returns the salary;
    • describe(), which returns the text <name> earns <pay>, such as Ana earns 3000.

    Manager inherits from Employee. It has an initializer Manager(name, salary, bonus) that stores the bonus itself and lets the parent store the name and the salary, and it overrides pay() to return the parent's pay() plus the bonus. It does not write describe() again.

    For Ana, an employee with salary 3000, describe() gives Ana earns 3000. For Bob, a manager with salary 4000 and bonus 1000, it gives Bob earns 5000.

    Approach

    The key idea is that describe() calls pay() instead of reading the salary. When describe() runs on a plain employee, pay() is the employee's version. When it runs on a manager, Swift calls the manager's overriding version, because a method call looks at the real type of the object. So the same describe() code shows the bonus for managers without being copied.

    The salary is private to Employee, so Manager can't read it. It gets the salary the proper way: by asking the parent's pay() through super. The parent decides how an employee is paid, and the manager adds its bonus on top.

    Step by step

    1. Declare private let name: String in Employee. Private means only code inside Employee uses it, not even Manager.
    2. Declare private let salary: Int the same way.
    3. Store both in init: self.name = name and self.salary = salary. Plain name is the parameter, self.name the property.
    4. pay() returns salary.
    5. describe() returns "\(name) earns \(pay())". The \( ) puts a value into a string, a number too. It calls pay(), not the salary property.
    6. Declare Manager: Employee. The : Employee gives it the name, the salary, pay and describe. Add its own private let bonus: Int.
    7. In Manager's init, store the bonus first: self.bonus = bonus. Swift requires a class to set its own properties before calling the parent's initializer.
    8. Then call super.init(name, salary). It runs Employee's initializer, the only code that can set the private name and salary.
    9. Override pay(): mark it override func pay() -> Int and return super.pay() + bonus.

    The solution in Swift

    class Employee {
        private let name: String
        private let salary: Int
    
        init(_ name: String, _ salary: Int) {
            self.name = name
            self.salary = salary
        }
    
        func pay() -> Int {
            return salary
        }
    
        func describe() -> String {
            return "\(name) earns \(pay())"
        }
    }
    
    class Manager: Employee {
        private let bonus: Int
    
        init(_ name: String, _ salary: Int, _ bonus: Int) {
            self.bonus = bonus
            super.init(name, salary)
        }
    
        override func pay() -> Int {
            return super.pay() + bonus
        }
    }
    

    Using both classes together in one array:

    let people: [Employee] = [Employee("Ana", 3000), Manager("Bob", 4000, 1000), Manager("Cleo", 5000, 0), Employee("Dan", 5000), Manager("Eve", 7000, 2500)]
    for p in people { print(p.describe()) }
    print(people[1].pay())
    
    Ana earns 3000
    Bob earns 5000
    Cleo earns 5000
    Dan earns 5000
    Eve earns 9500
    5000
    

    The array has the type [Employee], yet each manager in it still uses its own pay(). Cleo, whose bonus is 0, earns exactly the salary, like Dan.

    Swift details worth knowing

    • override is mandatory. Redefining a parent's method without it fails: overriding declaration requires an 'override' keyword. The keyword protects you from overriding something by accident.
    • Initializer order. Calling super.init(name, salary) before setting bonus fails with property 'self.bonus' not initialized at super.init call. In the other order, a subclass first initializes its own properties, then calls up.
    • Private is respected by subclasses. Writing salary + bonus inside Manager fails with 'salary' is inaccessible due to 'private' protection level. That is why the manager calls super.pay().
    • super.pay() versus pay(). Inside the override, pay() alone means "this same method", so it would call itself forever. The program crashes instead of returning a number.
    • A subclass gets describe() for free. Nothing in Manager mentions it, yet Manager("Bob", 4000, 1000).describe() works.

    Edge cases and common mistakes

    • Copying describe() into Manager. It would work now but forces two copies to stay in sync.
    • Describing with salary instead of pay(). Then managers would show only their salary: Bob would earn 4000.
    • A zero bonus. It must not change the pay.
    • Equal names. Two people may have the same name, and each object keeps its own values.

    Reading the call chain

    Follow Manager("Bob", 4000, 1000).describe() once. The manager has no describe() of its own, so Swift runs the one inherited from Employee. That code calls pay(), and since the object is a Manager, the override runs. The override calls super.pay(), which is Employee's version and returns the salary, 4000. Adding the bonus gives 5000, and the string becomes Bob earns 5000.

    Why not store the salary in Manager too?

    A second copy of the salary in Manager would work for the tests, but it is a design smell. The manager would then hold the same fact in two places, and a change to how employees are paid would need to be repeated. By asking super.pay(), the manager says only what makes it different: "the pay of an employee, plus a bonus". If Employee.pay() changed one day, for example to include a fixed allowance, every manager would follow automatically.

    Complexity

    Each call is constant time: pay() reads a field, the manager's pay() adds two numbers, and describe() builds one short string. Creating n people takes O(n) time and space in total.

    Testing

    • An employee Ana with 3000 and a manager Bob with 4000 and a bonus of 1000: Ana earns 3000 and Bob earns 5000.
    • A manager Cleo with 5000 and a bonus of 0, and an employee Dan with 5000: both lines say 5000.
    • A mix in any order, such as manager Eve 7000 + 2500: Eve earns 9500.
    Keep going with Swift500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free