What is Method Overriding?

Method Overriding means creating a new version of a parent class’s method in a child class. Instead of using the parent’s method, the child uses its own customized version.


Why Use Method Overriding?

  1. Customization - Each child class can have its own version of a method
  2. Polymorphism - Same method name, different behavior depending on the object type
  3. Flexibility - Child classes don’t need the parent’s exact behavior
  4. Code Reuse with Differences - Keep shared code in parent, customize in children
  5. Cleaner Code - Avoid tons of if-statements checking object types

Parent Class: Enemy

class Enemy {
    constructor(data = null, gameEnv = null) {
        this.gameEnv = gameEnv;
        this.playerDestroyed = false;
        this.position = { x: 0, y: 0 };
        this.velocity = { x: 0, y: 0 };
        // ... other properties
    }

    // Parent method - basic behavior
    handleCollisionEvent() {
        console.log("Generic collision event");
    }

    // Parent method - basic boundary check
    stayWithinCanvas() {
        // Stop at edges
        if (this.position.x < 0) this.position.x = 0;
        if (this.position.x > this.gameEnv.innerWidth) this.position.x = this.gameEnv.innerWidth;
    }
}

Child Class 1: Guard (Overrides Methods)

import Enemy from '@assets/js/GameEnginev1/essentials/Enemy.js';
import Player from '@assets/js/GameEnginev1/essentials/Player.js';

class Guard extends Enemy {
    constructor(data = null, gameEnv = null) {
        super(data, gameEnv);
        this.velocity.y = -3;
    }

    // Override: Guard has its own collision handling
    handleCollisionEvent() {
        var player = this.gameEnv.gameObjects.find(obj => obj instanceof Player);
        console.log("Collision has occurred, player has been destroyed.");
        player.destroy();
        this.playerDestroyed = true;
    }

    // Override: Guard bounces off edges instead of stopping
    stayWithinCanvas() {
        // Bottom of canvas
        if (this.position.y + this.height > this.gameEnv.innerHeight) {
            this.position.y = this.gameEnv.innerHeight - this.height;
            this.velocity.y *= -1;  // Bounce!
        }
        // Top of canvas
        if (this.position.y < 0) {
            this.position.y = 1;
            this.velocity.y *= -1;  // Bounce!
        }
        // Left and right
        if (this.position.x + this.width > this.gameEnv.innerWidth) {
            this.position.x = this.gameEnv.innerWidth - this.width;
            this.velocity.x = 0;
        }
        if (this.position.x < 0) {
            this.position.x = 0;
            this.velocity.x = 0;
        }
    }
}

Child Class 2: ExampleEnemy (Also Overrides)

import Enemy from '@assets/js/GameEnginev1/essentials/Enemy.js';
import Player from '@assets/js/GameEnginev1/essentials/Player.js';

class ExampleEnemy extends Enemy {
    constructor(data = null, gameEnv = null) {
        super(data, gameEnv);
    }

    // Override: ExampleEnemy has its own collision handling (same as Guard)
    handleCollisionEvent() {
        var player = this.gameEnv.gameObjects.find(obj => obj instanceof Player);
        console.log("Collision has occurred, player has been destroyed.");
        player.destroy();
        this.playerDestroyed = true;
    }

    // ExampleEnemy does NOT override stayWithinCanvas()
    // So it uses the parent Enemy's version
}

Try It Yourself

%%js // CODE_RUNNER: method-overriding class Character { attack() { return “Generic attack”; } } class Warrior extends Character { attack() { return “Sword attack!”; } } const warrior = new Warrior(); console.log(warrior.attack());