Classes & Inheritance (ES6+)

Prototype-এর উপর সিনট্যাক্স sugar — কিন্তু পরিষ্কার

~35 min Intermediate 16 practice problems Live runner

1. Class Basics

basics.js
class Person {
    constructor(name, age) {
        this.name = name;
        this.age  = age;
    }
    greet() {
        return `Hi, I'm ${this.name}`;
    }
}

const p = new Person("Arif", 22);
console.log(p.greet());

// Proof: still prototypes underneath
console.log(typeof Person);                        // "function"
console.log(Object.getPrototypeOf(p) === Person.prototype);
ES6 class আসলে prototype-এর উপর সিনট্যাক্স sugar — কিন্তু সিনট্যাক্স অনেক পরিষ্কার এবং পড়তে সহজ।

2. Static Methods & Class Fields

static.js
class Vector {
    // Public class field
    name = "vec";

    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    length() { return Math.hypot(this.x, this.y); }

    // Static — called on the class itself
    static zero() { return new Vector(0, 0); }
    static dim = 2;
}

const v = new Vector(3, 4);
console.log(v.length(), v.name);
console.log(Vector.zero(), Vector.dim);

3. Inheritance — extends & super

extends.js
class Animal {
    constructor(species) { this.species = species; }
    describe() { return `I am a ${this.species}`; }
}

class Dog extends Animal {
    constructor(name) {
        super("dog");          // must run before this
        this.name = name;
    }
    describe() {
        return super.describe() + ` named ${this.name}`;
    }
    bark() { return "Woof!"; }
}

const d = new Dog("Rex");
console.log(d.describe(), d.bark());
console.log(d instanceof Animal);    // true

4. Getters & Setters

getset.js
class Temperature {
    constructor(c) { this.c = c; }
    get f() { return this.c * 9 / 5 + 32; }
    set f(v) { this.c = (v - 32) * 5 / 9; }
}

const t = new Temperature(20);
console.log(t.f);   // 68
t.f = 100;
console.log(t.c);   // 37.7…

5. Private # Fields

private.js
class Account {
    #balance = 0;
    deposit(n) { this.#balance += n; }
    withdraw(n) {
        if (n > this.#balance) throw new Error("insufficient");
        this.#balance -= n;
    }
    get balance() { return this.#balance; }
}

const a = new Account();
a.deposit(100);
console.log(a.balance);          // 100
try { console.log(a.#balance); }     // SyntaxError outside class
catch (e) {}
Composition > Inheritance Don't reach for extends by default. Most production code is better served by composition — small classes that hold each other as fields — rather than tall inheritance trees.

6. Class Hoisting (Or Not)

hoist.js
try {
    new A();
} catch (e) {
    console.log("err:", e.message);
}
class A {}    // classes are NOT hoisted (TDZ like let)

new A();
console.log("ok");

7. Glossary (শব্দকোষ)

TermMeaningবাংলায়
classES6 syntactic sugar over prototypes for OOP.Prototype-এর উপর ES6 syntax sugar।
ConstructorSpecial method run on new ClassName().new ClassName()-এ যে method চলে।
StaticMethod/field on the class itself, not on instances.Instance-এ নয়, class-এ থাকা method/field।
extendsDeclares a subclass that inherits from a parent.Parent class থেকে subclass inherit করা।
superCalls the parent's constructor or methods.Parent-এর constructor বা method call করে।
Getter / SetterComputed property accessors via get/set.get/set দিয়ে computed property।
Private field #Field accessible only inside its own class.শুধু নিজের class-এর ভেতরে accessible।
CompositionReuse via "has-a" — one class holds another as a field."Has-a" pattern — এক class অন্যকে field হিসেবে রাখে।
মনে রাখুন: class আসলে prototype-এর উপর syntax sugar — typeof Class === "function"। Class declaration let/const-এর মতো hoisted নয় (TDZ আছে)। Subclass-এ this ব্যবহারের আগে super() call করতেই হবে। Inheritance থেকে composition বেশিরভাগ সময় ভালো — tall hierarchy এড়িয়ে চলুন।

8. Practice Problems

  1. Write a Rectangle class with width, height and an area() method.
    ✨ Show Answer
    a1.js
    class Rectangle {
        constructor(w, h) { this.w = w; this.h = h; }
        area() { return this.w * this.h; }
    }
    console.log(new Rectangle(5, 3).area());
  2. Add a static square(side) factory method.
    ✨ Show Answer
    a2.js
    class Rectangle {
        constructor(w, h) { this.w = w; this.h = h; }
        area() { return this.w * this.h; }
        static square(s) { return new Rectangle(s, s); }
    }
    console.log(Rectangle.square(5).area());
  3. Make Cube extend Rectangle: add depth and override area to return surface area.
    ✨ Show Answer
    a3.js
    class Rectangle {
        constructor(w, h) { this.w = w; this.h = h; }
        area() { return this.w * this.h; }
    }
    class Cube extends Rectangle {
        constructor(s) { super(s, s); this.d = s; }
        area() { return 6 * super.area(); }
    }
    console.log(new Cube(3).area());   // 54
  4. Build a Stopwatch class with start/elapsed methods.
    ✨ Show Answer
    a4.js
    class Stopwatch {
        #t0 = null;
        start() { this.#t0 = Date.now(); }
        elapsed() { return Date.now() - this.#t0; }
    }
    const sw = new Stopwatch();
    sw.start();
    for (let i = 0; i < 1e6; i++);
    console.log("ms:", sw.elapsed());
  5. Show that calling this before super() in a derived constructor errors.
    ✨ Show Answer
    a5.js
    class A {}
    try {
        class B extends A {
            constructor() { this.x = 1; super(); }
        }
        new B();
    } catch (e) {
        console.log("err:", e.message);
    }
  6. Build a Queue with enqueue, dequeue, and a size getter.
    ✨ Show Answer
    a6.js
    class Queue {
        #items = [];
        enqueue(x) { this.#items.push(x); }
        dequeue() { return this.#items.shift(); }
        get size() { return this.#items.length; }
    }
    const q = new Queue();
    q.enqueue("a"); q.enqueue("b");
    console.log(q.size, q.dequeue(), q.size);
  7. Define a getter fullName on a Person class.
    ✨ Show Answer
    a7.js
    class Person {
        constructor(f, l) { this.f = f; this.l = l; }
        get fullName() { return `${this.f} ${this.l}`; }
    }
    console.log(new Person("Arif", "Hossain").fullName);
  8. Use static method fromJSON to build an instance from a string.
    ✨ Show Answer
    a8.js
    class User {
        constructor(name, age) { this.name = name; this.age = age; }
        static fromJSON(s) { const { name, age } = JSON.parse(s); return new User(name, age); }
    }
    console.log(User.fromJSON('{"name":"Arif","age":22}'));
  9. Inherit and override toString for a Money class.
    ✨ Show Answer
    a9.js
    class Money {
        constructor(n) { this.n = n; }
        toString() { return `৳${this.n}`; }
    }
    console.log(`Total: ${new Money(99)}`);
  10. Build a Logger hierarchy (Logger → DebugLogger).
    ✨ Show Answer
    a10.js
    class Logger {
        log(m) { console.log("[INFO]", m); }
    }
    class DebugLogger extends Logger {
        log(m) { console.log("[DEBUG]", m); }
    }
    new DebugLogger().log("hi");
  11. Why is composition often preferred over inheritance?
    ✨ Show Answer

    Answer: Inheritance creates rigid trees: a change in the base ripples through every descendant; behaviours are coupled to the hierarchy. Composition gives the same reuse with looser bonds: a class holds a collaborator as a field and forwards calls, so each piece can be changed independently. Modern frameworks (React hooks, dependency injection) are largely composition-first.

  12. Use a private field to enforce a non-negative balance.
    ✨ Show Answer
    a12.js
    class Wallet {
        #b = 0;
        deposit(n) { if (n < 0) throw new Error("negative"); this.#b += n; }
        get balance() { return this.#b; }
    }
    const w = new Wallet();
    w.deposit(100);
    console.log(w.balance);
    try { w.deposit(-10); } catch (e) { console.log(e.message); }
  13. Test that a class instance is also an instance of Object.
    ✨ Show Answer
    a13.js
    class A {}
    const x = new A();
    console.log(x instanceof A, x instanceof Object);
  14. Class expression: assign a class to a variable and instantiate it.
    ✨ Show Answer
    a14.js
    const Box = class {
        constructor(v) { this.v = v; }
    };
    console.log(new Box(42).v);
  15. Use extends to add a method to all instances of Array… by subclassing.
    ✨ Show Answer
    a15.js
    class SafeArr extends Array {
        first() { return this[0]; }
        last()  { return this.at(-1); }
    }
    const a = SafeArr.from([10, 20, 30]);
    console.log(a.first(), a.last());
  16. Show that typeof Class === "function".
    ✨ Show Answer
    a16.js
    class A {}
    console.log(typeof A);   // "function"

Summary — Module 17

ES6 class is sweet syntax over the same prototype chain you saw last lecture. Classes give you constructor, methods, static members, getters/setters, private # fields, and clean extends/super. Classes are not hoisted. Favour composition over deep inheritance.

Class হলো prototype-এর উপর syntax sugar — কিন্তু পরিষ্কার। Inheritance ব্যবহার করতে পারেন, কিন্তু composition বেশিরভাগ সময় ভালো।

Next Module → Modules — import/export, ESM vs CommonJS।