Inheritance

July 5, 2025
1 views
0 comments
Inheritance

Section 1: The Concept of Inheritance

Inheritance is the process where one class, the child class, acquires (or inherits) the attributes and methods of another class, the parent class.

  • Parent Class (also called Superclass or Base Class): The class whose properties are being inherited. It's the general, original class.
  • Child Class (also called Subclass or Derived Class): The class that inherits from the parent. It's the new, more specialized class.

The "Is-A" Relationship: Inheritance establishes an "is-a" relationship. For example:

  • A Car is a Vehicle.
  • A Sparrow is a Bird.
  • A Manager is an Employee.

The child class automatically gets all the non-private attributes and methods of the parent class. It can then add new features of its own or modify the inherited ones.

Analogy: Think of it like family inheritance. You (the child class) inherit certain traits (attributes) like eye color and last name from your parents (the parent class). You also have your own unique traits, like your first name or a specific hobby. You can also take an inherited skill, like cooking, and add your own unique style to it.

Why use Inheritance?

  1. Code Reusability: Instead of writing the same code for a Car and a Truck, you can write it once in a Vehicle class and have both inherit it. This saves time and reduces errors.
  2. Logical Structure: It creates a natural hierarchy that is easy to understand and manage.

Section 2: Implementing Inheritance in Python

The syntax for inheritance in Python is straightforward. You simply put the name of the parent class in parentheses after the child class's name.

Syntax: class ChildClassName(ParentClassName): # Methods and attributes of the child class

Code Example:

# Parent Class (Superclass)
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        # A generic speak method
        print("This animal makes a sound.")

# Child Class (Subclass) that inherits from Animal
class Dog(Animal):
    # The Dog class automatically has __init__ and speak from Animal
    def bark(self):
        # This is a new method, specific to Dog
        print("Woof! Woof!")

# --- Using the classes ---

# Create an object of the parent class
generic_animal = Animal("Creature")
generic_animal.speak() # Output: This animal makes a sound.

# Create an object of the child class
my_dog = Dog("Buddy")

# my_dog can use the inherited 'name' attribute and 'speak' method
print(my_dog.name)        # Output: Buddy
my_dog.speak()            # Output: This animal makes a sound.

# my_dog can also use its own 'bark' method
my_dog.bark()             # Output: Woof! Woof!

Section 3: Method Overriding and the super() Function

This section deals with how a child class can modify the behavior it inherits from its parent.

Method Overriding

Sometimes, a child class needs to provide its own specific implementation of a method that it inherited from the parent class. This is called method overriding. The child class defines a method with the exact same name as a method in the parent class.

  • How it works: When the method is called on an object of the child class, Python will execute the child's version of the method, not the parent's.

Code Example (Extending the previous one):

class Cat(Animal):
    # We are overriding the 'speak' method from the Animal class
    def speak(self):
        print("Meow!")

my_cat = Cat("Whiskers")
my_cat.speak()  # This will call the Cat's version of speak(), not Animal's.

# Output: Meow!

Extending a Parent Method with super()

What if you don't want to completely replace the parent's method, but just add to it? For this, you use the super() function.

super() gives you a temporary object of the parent class, allowing you to call its methods from within the child class. This is extremely common when overriding the __init__() constructor.

  • Problem: A Manager is an Employee. An Employee has name and emp_id. A Manager has name, emp_id, and a team_size. How do we initialize a Manager object?
  • Solution: The Manager's __init__ method will first call the Employee's __init__ method to handle the name and emp_id (since that logic is already written), and then it will handle its own team_size.

Code Example:

class Employee:
    def __init__(self, name, emp_id):
        self.name = name
        self.emp_id = emp_id
        print(f"Employee '{self.name}' initialized.")

class Manager(Employee):
    def __init__(self, name, emp_id, team_size):
        # Call the parent's __init__ method using super()
        # This handles the name and emp_id initialization
        super().__init__(name, emp_id)

        # Now, initialize the attribute specific to the Manager
        self.team_size = team_size
        print(f"Manager '{self.name}' also initialized with team size {self.team_size}.")

# Creating a Manager object
mgr = Manager("Ravi", "E101", 15)

# Output:
# Employee 'Ravi' initialized.
# Manager 'Ravi' also initialized with team size 15.

Using super() avoids re-writing self.name = name and self.emp_id = emp_id in the Manager class.


Section 4: Types of Inheritance

This section briefly describes the different ways classes can be structured in an inheritance hierarchy.

  1. Single Inheritance: The simplest form. One child class inherits from one parent class. (All examples so far have been this). A -> B

  2. Multiple Inheritance: A child class inherits from more than one parent class. It gets features from all its parents.

    • Syntax: class Child(Parent1, Parent2):
    • Example: A FlyingCar class could inherit from both a Car class and an Airplane class. A -> C and B -> C
  3. Multilevel Inheritance: A class inherits from a child class, creating a "grandfather-father-son" relationship.

    • Example: Vehicle -> Car -> SportsCar. The SportsCar inherits from Car, which in turn inherits from Vehicle. The SportsCar gets features from both Car and Vehicle. A -> B -> C
  4. Hierarchical Inheritance: One parent class has multiple child classes that inherit from it.

    • Example: A Vehicle parent class has Car, Bus, and Bicycle as its children. A -> B and A -> C
  5. Hybrid Inheritance: A combination of two or more of the above types of inheritance. These can become complex but are used to model intricate real-world relationships.


Section 5: Abstract Methods (Detailed Explanation)

This section introduces an important design concept in Object-Oriented Programming. While standard inheritance allows child classes to optionally override parent methods, abstract methods introduce a rule: they force the child classes to provide their own implementation for certain methods.

What is an Abstract Method?

An abstract method is a method defined in a parent class that has a name and parameters, but no implementation or logic inside its body. It acts as a template or a required contract.

Any class that contains one or more abstract methods is called an Abstract Base Class (ABC). You cannot create objects (instances) directly from an Abstract Base Class. Its only purpose is to be inherited by other classes.

The Rule: Any subclass that inherits from an Abstract Base Class must provide a concrete (i.e., with a working body) implementation for all the abstract methods it inherited. If it fails to do so, it too becomes an abstract class, and you cannot create objects from it either.

Analogy: A Government Form Think of an Abstract Base Class as a government form template (e.g., a passport application form).

  • The form (Shape class) has required fields that you must fill out, like Name and Date of Birth. These are the abstract methods (area(), perimeter()).
  • The template itself is not a valid passport; you cannot submit a blank form. This is why you cannot create an object of an abstract class.
  • You (the child class, like Square or Circle) must take this form and fill in your specific details. You must provide your own implementation for the Name and Date of Birth fields.
  • If you submit the form with a required field left blank, it will be rejected. Similarly, if a subclass doesn't implement a required abstract method, Python will raise an error.

Why Use Abstract Methods?

  1. Enforcing a Common Interface: They guarantee that every subclass will have a certain set of methods, making them behave predictably. For example, you can be sure that any object whose class inherits from Shape will have a working .area() method, regardless of whether it's a Circle, Square, or Triangle.
  2. Framework Design: They are crucial for creating frameworks where you want other programmers to extend your base classes in a specific, structured way.

Implementing Abstract Methods in Python (The Simple Way)

While Python has a dedicated abc (Abstract Base Class) module for creating formal abstract classes, the textbook introduces a simpler, more conceptual way to achieve a similar effect using an error.

You define the method in the parent class and, instead of providing logic, you have it raise a NotImplementedError. This error explicitly tells the programmer that a subclass is responsible for implementing this logic.

Detailed Code Example from the Textbook:

# This is our Abstract Base Class, conceptually.
# It defines a contract for what a "Shape" should be able to do.
class Shape:
    def __init__(self, name):
        self.name = name

    def area(self):
        # This is the abstract method.
        # It has no code, just an error to force subclasses to implement it.
        raise NotImplementedError("Error: area() method must be implemented by the subclass")

    def perimeter(self):
        # Another abstract method.
        raise NotImplementedError("Error: perimeter() method must be in a subclass")

# --- Let's try to create a subclass that follows the rules ---

class Rectangle(Shape):
    def __init__(self, name, length, width):
        # Call the parent's constructor to set the name
        super().__init__(name)
        self.length = length
        self.width = width

    # Providing the required, concrete implementation for area()
    def area(self):
        return self.length * self.width

    # Providing the required, concrete implementation for perimeter()
    def perimeter(self):
        return 2 * (self.length + self.width)

# --- Now, let's create a subclass that BREAKS the rules ---

class Triangle(Shape):
    def __init__(self, name, base, height):
        super().__init__(name)
        self.base = base
        self.height = height

    # This class "forgets" to implement the perimeter() method.
    def area(self):
        return 0.5 * self.base * self.height

# --- Using the Objects ---

# 1. Using the 'Rectangle' class (which works correctly)
rect = Rectangle("My Rectangle", 10, 5)
print(f"Area of {rect.name} is: {rect.area()}")      # Output: Area of My Rectangle is: 50
print(f"Perimeter of {rect.name} is: {rect.perimeter()}") # Output: Perimeter of My Rectangle is: 30

# 2. Using the 'Triangle' class (which has a problem)
tri = Triangle("My Triangle", 10, 4)
print(f"Area of {tri.name} is: {tri.area()}")      # This works fine. Output: Area of My Triangle is: 20.0

# This next line will CRASH the program!
try:
    print(f"Perimeter of {tri.name} is: {tri.perimeter()}")
except NotImplementedError as e:
    print(e)  # The program crashes and prints the error message we wrote.

# Output of the last block:
# Area of My Triangle is: 20.0
# Error: perimeter() method must be in a subclass

Drawback of this Simple Method: As the textbook points out, the major drawback of using NotImplementedError is that the error only occurs when you actually try to call the unimplemented method. The program doesn't warn you when you define the Triangle class or even when you create the tri object. The error is delayed until runtime.

More advanced methods (like using the abc module) can catch this error earlier, right when you try to create an object of the incomplete subclass, which is generally safer for larger applications. However, for understanding the concept, the NotImplementedError approach is very clear and effective.

Arbind Singh

Teacher, Software developer

Innovative educator and tech enthusiast dedicated to empowering students through robotics, programming, and digital tools.

Comments (0)

You need to be signed in to post a comment.

Sign In

No comments yet

Be the first to share your thoughts and insights about this note!

Note Stats

Views1
Comments0
PublishedJuly 5, 2025

Related Notes

Introduction to Computer Science

Class 11 • Computer Science

Python Programming Basics

Class 12 • Computer Science

Database Management Systems

Class 12 • Informatics Practices

Part of Course

CBSE Class XII Computer Science with Python

Price
Free
Inheritance | StudyVatika Notes