Skip to content

8 min read

American Corners

Inheritance

Building on what already exists

Often several kinds of thing share most of their behaviour and differ only in a detail or two. A car and a bus are both vehicles: both have a make, both can start, both can report themselves. Writing two full classes that repeat all of that is wasteful, and worse, if you later fix a bug in the shared part you have to fix it in every copy.

Inheritance solves this. You write the shared behaviour once in a parent class (also called a base class), and each child class (or derived class) inherits it automatically, adding or changing only what makes it special. The child gets everything the parent has for free.

A parent class

Start with the general idea, a vehicle, and put the common parts there.

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

    def describe(self):
        return f"A {self.make} with {self.wheels} wheels"

Any vehicle can be described, and any vehicle records its make and how many wheels it has. This is the shared ground the children will stand on.

Children that inherit

A child class names its parent in parentheses. Straight away it has describe and the attributes, without repeating a line.

class Car(Vehicle):
    def open_boot(self):                 # something only a car does
        return f"The {self.make} boot is open"


class Bus(Vehicle):
    def __init__(self, make, wheels, seats):
        super().__init__(make, wheels)   # let the parent set up the shared parts
        self.seats = seats               # then add what is new

    def describe(self):                  # replace the parent's version
        return f"A {self.make} bus with {self.seats} seats"

Car adds a method of its own and otherwise leans entirely on Vehicle. Bus needs an extra attribute, seats, so it writes its own __init__, but instead of copying the parent's setup it calls super().__init__(...), which runs the parent's __init__ first. That single line is how a child reuses the parent's work rather than duplicating it.

car = Car("Fiat", 4)
bus = Bus("Setra", 6, 52)

print(car.describe())      # A Fiat with 4 wheels        (inherited unchanged)
print(car.open_boot())     # The Fiat boot is open       (car's own method)
print(bus.describe())      # A Setra bus with 52 seats   (bus's own version)

Overriding: same name, new behaviour

Notice that Bus defines its own describe. When a child writes a method with the same name as one in the parent, the child's version wins for objects of that child. This is called overriding, and it is how a child keeps most of the parent but changes the parts that should differ. car.describe() uses the inherited version; bus.describe() uses its own.

Tip

Reach for inheritance when you can honestly say "a child is a kind of parent": a car is a kind of vehicle, a savings account is a kind of account. If the sentence sounds wrong, for example "a wheel is a kind of car", then the thing is a part, not a child, and inheritance is the wrong tool.

Inheritance keeps the shared code in one place and lets each child stay small, holding only what is genuinely its own. Fix or improve the parent, and every child improves with it. In the next lesson you will see why children sharing method names is not just tidy but genuinely powerful.

Prefer to see it explained? Here is the recorded Code for Albania lecture on this topic.

Try this now

Write a parent class Animal with name and a speak() method that returns a generic sound. Make a child Dog(Animal) that overrides speak() to bark, and a child Cat(Animal) that adds an indoor attribute in its own __init__ using super().__init__(...). Build one of each and call speak() on both.

Check yourself

  1. What does a child class get from its parent without writing any code, and why does that reduce both effort and bugs?
  2. Bus calls super().__init__(make, wheels) inside its own __init__. What would go wrong, or be repeated, if it did not use super() and instead set every attribute by hand?
  3. Both Vehicle and Bus define a describe method. When you call bus.describe(), which one runs, and what is that behaviour called?

Where this lesson comes from

Built from

  • Data Structures and Algorithms

alphaPlan courses are built from taught programmes rather than invented for the web. Where a claim rests on an outside standard or a reported case, it is named above so you can check it rather than take our word for it.

This course was developed by alphaPlan Center from programs delivered in partnership with the American Corners network.

Found something unclear, outdated or improvable? Suggest an improvement