DEV Community

Programming Entry Level: tutorial inheritance

Understanding Tutorial Inheritance for Beginners

Have you ever noticed how a puppy is like a dog, but also has its own unique characteristics? That's the core idea behind inheritance in programming! It's a powerful concept that lets you create new things based on existing ones, saving you time and making your code more organized. Understanding inheritance is a common topic in programming interviews, and it's a fundamental building block for larger projects. Let's dive in!

Understanding "Tutorial Inheritance"

Imagine you're building a game with different types of characters: warriors, mages, and archers. Each character has some common traits – like health, name, and the ability to attack. Instead of writing the code for these common traits separately for each character type, we can use inheritance.

Think of it like this: you have a general blueprint for a "Character." This blueprint defines the basic properties and actions all characters share. Then, you can create more specific blueprints – "Warrior," "Mage," and "Archer" – that inherit from the "Character" blueprint. They automatically get all the properties and actions of a character, and then you can add their own unique abilities.

In programming terms, the "Character" is called the parent class (or sometimes the base class), and the "Warrior," "Mage," and "Archer" are called child classes (or derived classes). The child classes inherit the properties and methods of the parent class.

Here's a simple visual representation using a mermaid diagram:

classDiagram
    class Character {
        +name: string
        +health: int
        +attack()
    }
    class Warrior {
        +armor: int
        +specialAttack()
    }
    class Mage {
        +mana: int
        +castSpell()
    }
    class Archer {
        +arrows: int
        +shoot()
    }
    Warrior --|> Character
    Mage --|> Character
    Archer --|> Character
Enter fullscreen mode Exit fullscreen mode

This diagram shows that Warrior, Mage, and Archer all inherit from Character. The --|> symbol means "inherits from."

Basic Code Example

Let's see how this looks in Python:

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

    def speak(self):
        print("Generic animal sound")

class Dog(Animal):
    def speak(self):
        print("Woof!")

class Cat(Animal):
    def speak(self):
        print("Meow!")

# Create instances

animal = Animal("Generic Animal")
dog = Dog("Buddy")
cat = Cat("Whiskers")

# Call the speak method

animal.speak()
dog.speak()
cat.speak()
Enter fullscreen mode Exit fullscreen mode

Let's break this down:

  1. class Animal: creates a class called Animal. This is our parent class.
  2. __init__(self, name): is the constructor. It's called when you create a new Animal object. It takes the animal's name as input and stores it.
  3. self.name = name assigns the input name to the object's name attribute.
  4. def speak(self): defines a method called speak. This is what happens when you call animal.speak().
  5. class Dog(Animal): creates a class called Dog that inherits from Animal. The (Animal) part is crucial – it tells Python that Dog is a child class of Animal.
  6. The Dog class overrides the speak method. This means it provides its own version of the speak method, which is specific to dogs.
  7. The Cat class does the same, providing its own speak method.
  8. Finally, we create instances of each class and call their speak methods. Notice how each object calls its own specific speak method, even though they all inherited from Animal.

Common Mistakes or Misunderstandings

Here are a few common pitfalls when learning inheritance:

❌ Incorrect code:

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

class Dog(Animal):
    def __init__(self):
        print("Woof!")
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

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

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name) # Call the parent's constructor

        print("Woof!")
Enter fullscreen mode Exit fullscreen mode

Explanation: If you define an __init__ method in the child class, you need to explicitly call the parent class's __init__ method using super().__init__(...) to initialize the inherited attributes. Otherwise, the child class won't have the name attribute.

❌ Incorrect code:

class Animal:
    def speak(self):
        print("Generic animal sound")

class Dog(Animal):
    def speak(): # Missing 'self'

        print("Woof!")
Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

class Animal:
    def speak(self):
        print("Generic animal sound")

class Dog(Animal):
    def speak(self): # 'self' is required for instance methods

        print("Woof!")
Enter fullscreen mode Exit fullscreen mode

Explanation: All instance methods (methods that operate on an object) need to have self as the first parameter. Forgetting self will cause errors.

❌ Incorrect code:

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

class Dog(Animal):
    def eat(self):
        print("Dog is eating")

dog = Dog("Buddy")
dog.fly() # Animal doesn't have a fly method

Enter fullscreen mode Exit fullscreen mode

✅ Corrected code:

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

class Dog(Animal):
    def eat(self):
        print("Dog is eating")

dog = Dog("Buddy")
dog.eat() # Call a valid method

Enter fullscreen mode Exit fullscreen mode

Explanation: Child classes only inherit methods from their parent class. Trying to call a method that doesn't exist will result in an error.

Real-World Use Case

Let's create a simple system for managing different types of vehicles.

class Vehicle:
    def __init__(self, make, model):
        self.make = make
        self.model = model

    def start_engine(self):
        print("Engine started")

class Car(Vehicle):
    def __init__(self, make, model, num_doors):
        super().__init__(make, model)
        self.num_doors = num_doors

    def honk(self):
        print("Beep beep!")

class Motorcycle(Vehicle):
    def __init__(self, make, model, has_sidecar):
        super().__init__(make, model)
        self.has_sidecar = has_sidecar

    def wheelie(self):
        print("Doing a wheelie!")

# Create instances

my_car = Car("Toyota", "Camry", 4)
my_motorcycle = Motorcycle("Harley-Davidson", "Sportster", False)

# Use the methods

my_car.start_engine()
my_car.honk()
my_motorcycle.start_engine()
my_motorcycle.wheelie()
Enter fullscreen mode Exit fullscreen mode

This example demonstrates how inheritance allows us to define common vehicle properties in the Vehicle class and then add specific features to Car and Motorcycle without repeating code.

Practice Ideas

Here are some exercises to help you solidify your understanding:

  1. Shape Hierarchy: Create a Shape class with methods for calculating area and perimeter. Then, create Circle and Rectangle classes that inherit from Shape and implement their own area and perimeter calculations.
  2. Employee Management: Create an Employee class with attributes like name and salary. Then, create Manager and Developer classes that inherit from Employee and add specific attributes like team size (for Manager) and programming language (for Developer).
  3. Animal Sounds (Extended): Expand the Animal example to include more animals (e.g., Cow, Pig, Bird) and add more methods (e.g., eat(), sleep()).
  4. Simple Game Characters: Create a Character class with health and attack power. Then, create Warrior, Mage, and Archer classes that inherit from Character and have unique abilities.
  5. Library Books: Create a Book class with title, author, and publication year. Then, create FictionBook and NonFictionBook classes that inherit from Book and add specific attributes like genre (for FictionBook) and subject (for NonFictionBook).

Summary

Congratulations! You've taken your first steps into the world of inheritance. You've learned that inheritance allows you to create new classes based on existing ones, promoting code reuse and organization. Remember the key concepts: parent class, child class, and overriding methods. Don't be afraid to experiment and practice – the more you use inheritance, the more comfortable you'll become with it.

Next, you might want to explore more advanced concepts like multiple inheritance and abstract classes. Keep learning, keep coding, and have fun!

Top comments (0)