12-2. Understanding the "is a" Relationship in Inheritance

In object-oriented programming (OOP), the concept of inheritance helps us represent the "is a" relationship between objects. This means that one object is a specialized version of another object. Let's look at some real-world examples:

  • A car is a vehicle.
  • A rose is a flower.
  • A circle is a shape.
  • A tree is a plant.

When an "is a" relationship exists, the specialized object (like a rose) has all the characteristics of the general object (like a flower) plus some additional characteristics that make it special.

Example:

Let’s create a Car superclass and two subclasses: RV and Truck. The Car class will have common attributes, while RV and Truck will have additional unique attributes.

Superclass: Car

class Car:
    def __init__(self, make="", model="", year=0):
        self.make = make
        self.model = model
        self.year = year

    def print_info(self):
        print(f"A {self.year} {self.make} {self.model}. Impressed?")

 

  • Attributes: make, model, and year are common to all cars.
  • Method: print_info() prints out information about the car.

Subclass 1: RV

class RV(Car): # RV inherits from Car
    def __init__(self, make, model, year, rv_type):
        super().__init__(make, model, year) # Call the constructor of Car
        self.rv_type = rv_type

    def print_info(self):
        print(f"A {self.year} {self.make} {self.model} RV of type {self.rv_type}. Impressed?")

 

  • Inheritance: By using class RV(Car):, we declare that RV is a subclass of Car.
  • Calling the Superclass Constructor: super().__init__(make, model, year) initializes the common attributes.
  • New Attribute: rv_type is a new attribute unique to RV.
  • Overriding a Method: print_info() is redefined in RV to include rv_type.

Subclass 2: Truck

class Truck(Car): # Truck inherits from Car
    def __init__(self, make, model, year, capacity):
        super().__init__(make, model, year) # Call the constructor of Car
        self.capacity = capacity

    def print_info(self):
        print(f"A {self.year} {self.make} {self.model} Truck with a capacity of {self.capacity} tons. Impressed?")

 

  • Inheritance: By using class Truck(Car):, we declare that Truck is a subclass of Car.
  • Calling the Superclass Constructor: super().__init__(make, model, year) initializes the common attributes.
  • New Attribute: capacity is a new attribute unique to Truck.
  • Overriding a Method: print_info() is redefined in Truck to include capacity.

Creating Objects and Using Inherited Methods

Let’s create objects of RV and Truck and see how inheritance works:

  • Creating and Using an RV Object
my_rV = RV("Winnebago", "Vista", 2021, "Class A")
my_rV.print_info() # A 2021 Winnebago Vista RV of type Class A. Impressed?

 

  • Creating and Using a Truck Object
my_truck = Truck("Ford", "F-150", 2022, 3)
my_truck.print_info() # A 2022 Ford F-150 Truck with a capacity of 3 tons. Impressed?

 

Key Points

  • Superclass and Subclass: Car is the superclass, and RV and Truck are subclasses.
  • Inheritance: Both RV and Truck inherit attributes and methods from Car.
  • Constructor Call: super().__init__(make, model, year) ensures that the Car constructor is called.
  • Method Overriding: The print_info() method in both RV and Truck overrides the method in Car.