~/
hackweb.dev
JavaScript Inheritance & extends
Quiz
⌘K
...
~/
/tutorials
/js/js-inheritance/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/js/21js-inheritance
Write
Preview
Diff
# JavaScript Inheritance & extends Create specialized classes from parent classes using `extends`. ## Basic Inheritance ```javascript class Animal { constructor(name) { this.name = name; } speak() { return `${this.name} makes a sound`; } } class Dog extends Animal { speak() { return `${this.name} barks`; } } let dog = new Dog("Rex"); console.log(dog.speak()); // "Rex barks" ``` `Dog` inherits `name` from `Animal` and overrides `speak()`. ## The super Keyword ```javascript class Dog extends Animal { constructor(name, breed) { super(name); // Call parent constructor this.breed = breed; } describe() { return `${super.describe()} (${this.breed})`; } } ``` **Remember:** Call `super()` before using `this` in a child constructor. ## Method Overriding & Polymorphism ```javascript class Shape { constructor(name) { this.name = name; } getArea() { throw new Error("getArea() must be implemented"); } toString() { return `${this.name} with area ${this.getArea()}`; } } class Circle extends Shape { constructor(r) { super("Circle"); this.radius = r; } getArea() { return Math.PI * this.radius ** 2; } } class Rectangle extends Shape { constructor(w, h) { super("Rectangle"); this.w = w; this.h = h; } getArea() { return this.w * this.h; } } [new Circle(5), new Rectangle(4, 6)].forEach(s => console.log(s.toString())); // "Circle with area 78.539..." // "Rectangle with area 24" ``` Same `toString()`, different results — this is **polymorphism**. ## Complete Example: Employee System ```javascript class Employee { constructor(name, salary) { this.name = name; this.salary = salary; } getBonus() { return this.salary * 0.1; } describe() { return `${this.name}: $${this.salary} + $${this.getBonus()} bonus`; } } class Manager extends Employee { constructor(name, salary, dept) { super(name, salary); this.department = dept; this.reports = []; } getBonus() { return this.salary * 0.2; } addReport(emp) { this.reports.push(emp); return this; } describe() { return `${super.describe()} (Manager of ${this.department})`; } } class Developer extends Employee { constructor(name, salary, langs) { super(name, salary); this.languages = langs; } getBonus() { return this.salary * 0.15; } describe() { return `${super.describe()} (Dev: ${this.languages.join(", ")})`; } } let dev = new Developer("Alice", 80000, ["JS", "Python"]); let mgr = new Manager("John", 120000, "Engineering"); console.log(dev.describe()); // "Alice: $80000 + $12000 bonus (Dev: JS, Python)" console.log(mgr.describe()); // "John: $120000 + $24000 bonus (Manager of Engineering)" ``` Each subclass overrides `getBonus()` with a different rate — same interface, different behavior. ## Best Practices - **Use `extends` for "is-a" relationships** — Dog is an Animal - **Call `super()` first** — Before using `this` in child constructor - **Override methods carefully** — Maintain the parent's interface - **Keep hierarchies shallow** — Deep inheritance is hard to maintain - **Prefer composition** — "Has-a" often beats "is-a" ## Common Mistakes - **Forgetting `super()`** — Required in child constructor - **Overriding with different parameters** — Breaks the interface contract - **Deep inheritance chains** — Hard to maintain and debug - **Not returning `this`** — Breaks method chaining
No changes yet
Reset to original
Submit suggestion
cancel