A child class can override a parent method to provide specialized behavior.

override An overriding method has the same name as the parent method and runs for the child instance.

Method Overriding

rawMessage
override.ts
Replay: real traced execution (multi-file project)
class Notification {
    message: string;

    constructor(message: string) {
        this.message = message;
    }

    format(): string {
        return this.message;
    }
}

class UrgentNotification extends Notification {
    format(): string {
        return `URGENT: ${this.message.toUpperCase()}`;
    }
}

const rawMessage: string = "build passed";
const notice: Notification = new UrgentNotification(rawMessage);
const formatted: string = notice.format();

console.log(formatted);
class Notification {
    message: string;

    constructor(message: string) {
        this.message = message;
    }

    format(): string {
        return this.message;
    }
}

class UrgentNotification extends Notification {
    format(): string {
        return `URGENT: ${this.message.toUpperCase()}`;
    }
}

const rawMessage: string = "tests failed";
const notice: Notification = new UrgentNotification(rawMessage);
const formatted: string = notice.format();

console.log(formatted);
class Notification {
    message: string;

    constructor(message: string) {
        this.message = message;
    }

    format(): string {
        return this.message;
    }
}

class UrgentNotification extends Notification {
    format(): string {
        return `URGENT: ${this.message.toUpperCase()}`;
    }
}

const rawMessage: string = "deploy ready";
const notice: Notification = new UrgentNotification(rawMessage);
const formatted: string = notice.format();

console.log(formatted);
  1. rawMessage ← build passed, this.message ← build passed, notice ← [object Object]

    4    constructor(message: string) {5        this.message = messagebuild passed;6    }78    format(): string {9        return this.message;10    }11}1213class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.message.toUpperCase()}`;16    }17}1819const rawMessage→ build passed: string = "build passed";  //@rawMessage="tests failed", "deploy ready"20const notice→ [object Object]: Notification = new UrgentNotification(rawMessagebuild passed);21const formatted: string = notice[object Object].format();
    values this stepbuild passedthis.message
  2. format(): string

    13class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.messagebuild passed.toUpperCase()}`;16    }
  3. formatted ← URGENT: BUILD PASSED

    19const rawMessage: string = "build passed";  //@rawMessage="tests failed", "deploy ready"20const notice: Notification = new UrgentNotification(rawMessage);21const formatted→ URGENT: BUILD PASSED: string = notice[object Object].format();2223console.log(formattedURGENT: BUILD PASSED);
    outputURGENT: BUILD PASSED
  1. rawMessage ← tests failed, this.message ← tests failed, notice ← [object Object]

    4    constructor(message: string) {5        this.message = messagetests failed;6    }78    format(): string {9        return this.message;10    }11}1213class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.message.toUpperCase()}`;16    }17}1819const rawMessage→ tests failed: string = "tests failed";20const notice→ [object Object]: Notification = new UrgentNotification(rawMessagetests failed);21const formatted: string = notice[object Object].format();
    values this steptests failedthis.message
  2. format(): string

    13class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.messagetests failed.toUpperCase()}`;16    }
  3. formatted ← URGENT: TESTS FAILED

    19const rawMessage: string = "tests failed";20const notice: Notification = new UrgentNotification(rawMessage);21const formatted→ URGENT: TESTS FAILED: string = notice[object Object].format();2223console.log(formattedURGENT: TESTS FAILED);
    outputURGENT: TESTS FAILED
  1. rawMessage ← deploy ready, this.message ← deploy ready, notice ← [object Object]

    4    constructor(message: string) {5        this.message = messagedeploy ready;6    }78    format(): string {9        return this.message;10    }11}1213class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.message.toUpperCase()}`;16    }17}1819const rawMessage→ deploy ready: string = "deploy ready";20const notice→ [object Object]: Notification = new UrgentNotification(rawMessagedeploy ready);21const formatted: string = notice[object Object].format();
    values this stepdeploy readythis.message
  2. format(): string

    13class UrgentNotification extends Notification {14    format(): string {15        return `URGENT: ${this.messagedeploy ready.toUpperCase()}`;16    }
  3. formatted ← URGENT: DEPLOY READY

    19const rawMessage: string = "deploy ready";20const notice: Notification = new UrgentNotification(rawMessage);21const formatted→ URGENT: DEPLOY READY: string = notice[object Object].format();2223console.log(formattedURGENT: DEPLOY READY);
    outputURGENT: DEPLOY READY

Follow the Override

  1. rawMessage starts as build passed.
  2. The variable type is Notification, but the object is new UrgentNotification(rawMessage).
  3. Calling notice.format() runs the child override.
  4. The override uppercases the message.
  5. The output is URGENT: BUILD PASSED. | message | method used | output | | --- | --- | --- | | build passed | child format() | URGENT: BUILD PASSED | | tests failed | child format() | URGENT: TESTS FAILED | | deploy ready | child format() | URGENT: DEPLOY READY |

Exercise: override.ts

Reproduce URGENT: BUILD PASSED, then use the pinned rawMessage variants tests failed and deploy ready to predict URGENT: TESTS FAILED and URGENT: DEPLOY READY.