PROGRAMMING-CONCEPTS

Inheritance: Definition, Purpose, and Examples

Inheritance is a core concept in object-oriented programming (OOP) that lets one class build on another. A new class (called a subclass or child class) can reuse, extend, or modify the behavior of an existing class (called the superclass or parent class). This helps reduce duplication, organize code logically, and support more flexible software architectures.

Developers use inheritance when different objects share common traits but need their own custom behavior. It creates a natural hierarchy—general concepts at the top, specific ones below.


How Inheritance Works

At its simplest, inheritance allows a subclass to:

  • Reuse the parent’s properties and methods
  • Add new behavior
  • Override existing behavior

This helps avoid rewriting the same logic across multiple classes.

For example, many apps have a general User type. Admin users, guests, and members share basic traits but also have unique ones. Inheritance lets each role extend the general definition without duplicating everything.


Inheritance in Python

Python supports class inheritance with a simple syntax.

class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Hello, {self.name}"

class Admin(User):  # Admin inherits from User
    def delete_post(self):
        return f"{self.name} deleted a post"

Here, Admin inherits greet() from User. It also adds its own behavior.

Overriding a parent method

class Admin(User):
    def greet(self):
        return f"Welcome back, Admin {self.name}"

Now the child class replaces the parent’s version of greet() with something more specific.


Inheritance in JavaScript and TypeScript

Modern JavaScript (ES6+) uses the class and extends keywords.

class User {
  constructor(name) {
    this.name = name;
  }
  greet() {
    return `Hello, ${this.name}`;
  }
}

class Admin extends User {
  deletePost() {
    return `${this.name} deleted a post`;
  }
}

Method overriding with super

class Admin extends User {
  greet() {
    return `Admin access granted: ${super.greet()}`;
  }
}

super.greet() calls the parent method so the subclass can build on top of it.

TypeScript works the same way but adds type checking for safer inheritance.


Inheritance in Swift

Swift uses a similar syntax with clean, expressive rules.

class User {
    var name: String
    init(name: String) {
        self.name = name
    }
    func greet() -> String {
        return "Hello, \(name)"
    }
}

class Admin: User {
    func deletePost() -> String {
        return "\(name) deleted a post"
    }
}

Overriding behavior

class Admin: User {
    override func greet() -> String {
        return "Welcome back, Admin \(name)"
    }
}

Swift requires override to make it clear you’re intentionally replacing a parent method.


When to Use Inheritance

Inheritance works well when there’s a clear “is-a” relationship between types.

1. When multiple classes share a foundation

For example:

  • A Button, TextField, and Checkbox all extend from UIElement.
  • In a game, Enemy, NPC, and Player extend from Character.

Some behaviors repeat across these types, so inheritance avoids rewriting them.

2. When you want predictable structure

Subclasses naturally follow the parent’s shape. That makes the codebase easier to reason about.

3. When specialized behavior grows

A child class can override or extend functions as the app evolves. It’s a clean way to evolve a model without restructuring every file.

4. When modeling real-world concepts

Many relationships mirror actual categories:

“Car is a Vehicle,”

“Admin is a User,”

“Circle is a Shape.”

Inheritance expresses those hierarchies directly in code.


Examples of Inheritance in Action

Example 1: A basic class hierarchy (Python)

class Vehicle:
    def move(self):
        return "Moving"

class Car(Vehicle):
    def move(self):
        return "Driving on the road"

class Boat(Vehicle):
    def move(self):
        return "Sailing on water"

Each subclass specializes the parent method, making the behavior match the type.


Example 2: React class components

Functional components dominate modern React, but class components still illustrate inheritance in JavaScript.

class BaseComponent extends React.Component {
  log(message) {
    console.log("LOG:", message);
  }
}

class Dashboard extends BaseComponent {
  render() {
    this.log("Dashboard rendered");
    return <h1>Dashboard</h1>;
  }
}

Dashboard inherits log(), showing how shared behavior can move to a parent class.


Example 3: Sharing utilities in Swift

class Animal {
    func speak() -> String {
        return "Some generic sound"
    }
}

class Dog: Animal {
    override func speak() -> String {
        return "Woof!"
    }
}

The parent defines broad behavior, and the child refines it.


Inheritance vs Composition

Although inheritance is powerful, it’s not always the best choice. Developers often pair it with or replace it with composition — combining objects instead of extending them.

Inheritance example

“Admin” extends “User” to get its basic abilities.

Composition example

A “User” might have a “Permissions” object rather than extending from it.

Composition works better when:

  • You don’t want deep inheritance chains
  • Different objects share behavior but don’t fit a strict hierarchy
  • You want more flexibility in how features mix and match

For example, React uses composition extensively through passing components as props.


Inheritance Across Languages: Key Differences

Python

  • Multiple inheritance is allowed
  • Very flexible but requires careful design

JavaScript/TypeScript

  • Single inheritance
  • Mixins can mimic multiple inheritance

Swift

  • Single inheritance
  • Protocols provide flexible behavior sharing

These differences shape how developers design class hierarchies, but the core idea—reusing and extending behavior—stays consistent.


When Inheritance Is a Bad Fit

Inheritance starts to break down when:

  • The hierarchy becomes too deep
  • Subclasses override too much of the parent behavior
  • Relationships are forced (“Square extends Rectangle” is a classic problematic example)

Composition or standalone utilities usually solve these cases better.


Summary

Inheritance lets one class reuse and extend another class’s functionality. It supports clean hierarchy, reduces repetition, and helps organize large codebases. Python, JavaScript/TypeScript, and Swift all provide straightforward inheritance patterns, each with their own rules. It works best when subclasses naturally fit the “is-a” relationship and need shared behavior with customization. When models grow too complex, composition can offer a more flexible alternative.

Learn to Code for Free
Start learning now
button icon
To advance beyond this tutorial and learn to code by doing, try the interactive experience of Mimo. Whether you're starting from scratch or brushing up your coding skills, Mimo helps you take your coding journey above and beyond.

Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.

Reach your coding goals faster