Welcome to an enriching lesson where we’ll delve into the powerful concepts of Inheritance and Polymorphism in Python. Inheritance allows us to create a new class based on an existing one, promoting code reuse and extensibility. Polymorphism, on the other hand, empowers objects to take on multiple forms, enhancing flexibility and readability. In this lesson, we’ll explore the intricacies of creating subclasses, understanding inheritance, and implementing polymorphism.

Inheritance:

1. Definition:

2. Creating a Subclass:

class ElectricCar(Car):  # Assuming a Car class exists
    pass  # Placeholder for class definition

3. Overriding Methods:

class ElectricCar(Car):
    def display_info(self):
        print(f"{self.make} {self.model} (Electric)")

Polymorphism:

4. Definition:

5. Implementing Polymorphism:

car1 = Car("Toyota", "Camry")
car2 = ElectricCar("Tesla", "Model S")

def display_car_info(car):
    car.display_info()

display_car_info(car1)  # Calls the display_info method of the Car class
display_car_info(car2)  # Calls the overridden display_info method of the ElectricCar class

Example:

Let’s explore a practical example where we create a Dog class as a base class and a Poodle class as a subclass with additional attributes and methods.

# Example Code
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self):
        print("Woof!")

class Poodle(Dog):
    def __init__(self, name, age, color):
        super().__init__(name, age)  # Calling the constructor of the base class
        self.color = color

    def speak(self):  # Overriding the speak method
        print("Bark softly!")

    def show_details(self):
        print(f"Name: {self.name}, Age: {self.age}, Color: {self.color}")

# Creating objects (instances)
dog = Dog("Buddy", 3)
poodle = Poodle("Charlie", 2, "White")

# Accessing methods
dog.speak()  # Outputs "Woof!"
poodle.speak()  # Outputs "Bark softly!"

# Accessing subclass-specific method
poodle.show_details()

Practice Exercise:

Create a Python script that defines a base class Shape with attributes width and height and a method calculate_area. Create two subclasses, Rectangle and Triangle, each with its own implementation of calculate_area. Instantiate objects of each class and call their calculate_area methods.

# Example Practice Exercise
class Shape:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def calculate_area(self):
        pass  # Placeholder for method implementation

class Rectangle(Shape):
    def calculate_area(self):
        return self.width * self.height

class Triangle(Shape):
    def calculate_area(self):
        return 0.5 * self.width * self.height

# Creating objects (instances)
rectangle = Rectangle(4, 6)
triangle = Triangle(3, 5)

# Calculating and displaying areas
print("Rectangle Area:", rectangle.calculate_area())  # Outputs 24
print("Triangle Area:", triangle.calculate_area())    # Outputs 7.5

Summary:

In this detailed lesson, we’ve explored the concepts of Inheritance and Polymorphism in Python. Creating subclasses allows us to build on existing classes, promoting code reuse and extensibility. Polymorphism, achieved through method overriding, enhances flexibility in handling objects. Practice implementing inheritance and polymorphism to solidify your understanding, and feel free to ask questions in the discussion forum. As we advance, we’ll delve into more advanced OOP concepts and techniques!

Hands-on Practice

In this section, you will apply the concepts of inheritance and polymorphism through practical exercises to gain a deeper understanding of their application.

Exercise 1: Creating a Vehicle Class

  1. Create a base class named Vehicle with the following attributes:

Java

class Vehicle {
  private String make;
  private String model;
  private int year;
}
  1. Add methods to initialize these attributes, get their values, and display the vehicle details.

Java

public Vehicle(String make, String model, int year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

public String getMake() {
  return make;
}

public String getModel() {
  return model;
}

public int getYear() {
  return year;
}

public void displayVehicleDetails() {
  System.out.println("Vehicle Details:");
  System.out.println("Make: " + this.make);
  System.out.println("Model: " + this.model);
  System.out.println("Year: " + this.year);
}

Exercise 2: Creating Car and Motorcycle Subclasses

  1. Derive two subclasses from the Vehicle class: Car and Motorcycle.

Java

class Car extends Vehicle {
  private int numberOfWheels;
  private String fuelType;

  public Car(String make, String model, int year, int numberOfWheels, String fuelType) {
    super(make, model, year);
    this.numberOfWheels = numberOfWheels;
    this.fuelType = fuelType;
  }

  public int getNumberOfWheels() {
    return numberOfWheels;
  }

  public String getFuelType() {
    return fuelType;
  }
}

class Motorcycle extends Vehicle {
  private String engineType;

  public Motorcycle(String make, String model, int year, String engineType) {
    super(make, model, year);
    this.engineType = engineType;
  }

  public String getEngineType() {
    return engineType;
  }
}
  1. Each subclass should have additional attributes specific to its type.

Exercise 3: Implementing Polymorphism with Vehicle Methods

  1. Create methods in the Vehicle class for actions like start, stop, and move.

Java

public void start() {
  System.out.println("Starting vehicle");
}

public void stop() {
  System.out.println("Stopping vehicle");
}

public void move() {
  System.out.println("Moving vehicle");
}
  1. These methods should be implemented using polymorphism, allowing objects of both Car and Motorcycle classes to perform these actions in their respective ways.

Exercise 4: Creating a Vehicle Selector Class

  1. Design a class named VehicleSelector that allows users to create and manage vehicles of different types.

Java

class VehicleSelector {
  private List<Vehicle> vehicleList;

  public VehicleSelector() {
    vehicleList = new ArrayList<>();
  }

  public void addVehicle(Vehicle vehicle) {
    vehicleList.add(vehicle);
  }

  public void removeVehicle(Vehicle vehicle) {
    vehicleList.remove(vehicle);
  }

  public void manageVehicleFleet() {
    for (Vehicle vehicle : vehicleList) {
      vehicle.start();
      vehicle.move();
      vehicle.stop();
    }
  }
}
  1. The VehicleSelector class should have methods for adding vehicles, removing vehicles, and managing a fleet of vehicles.

Hands-on Quiz:

  1. What is the purpose of inheritance in OOP?

Inheritance allows classes to inherit properties and methods from other classes, promoting code reuse and adaptability.

  1. How do you create a subclass from an existing class?

To create a subclass from an existing class, use the extends keyword followed by the name of the parent class.

  1. What is polymorphism and how is it achieved?

Polymorphism refers to the ability of objects of different classes to respond to the same message in different ways. It is achieved through overloading and overriding methods.

  1. Explain the difference between overloading and overriding methods.

Overloading involves defining multiple methods with the same name but different parameter lists. Overriding involves redefining a method in a subclass with the same signature as the parent class method.

  1. Give an example of polymorphism in action using the Animal and Dog classes.

Consider the makeSound() method in the Animal and Dog classes. When a Dog object invokes the makeSound() method, it will call the overridden method specific to dogs, demonstrating polymorphism.

  1. How does inheritance promote code reusability?

Inheritance promotes code reusability by allowing classes to share common functionality and attributes. This reduces development time, effort, and the risk of introducing errors.

  1. How does polymorphism enhance flexibility in software development?

Polymorphism enables objects of different classes to respond to the same message in different ways, adapting to changing requirements and providing a more flexible and adaptable software design.

  1. What are the benefits of maintaining organized code using inheritance and polymorphism?

Inheritance and polymorphism make code more organized, easier to understand, and less prone to errors. This improves maintainability and code readability.

  1. Demonstrate polymorphism in a code example using the Vehicle and Car classes.

Create a VehicleSelector class that creates a Car object and calls the start() method. The start() method will be polymorphic because it will call the appropriate start() method for the Car class.

  1. Explain the concept of a vehicle fleet and how it can be managed using inheritance and polymorphism.

A vehicle fleet can be managed using inheritance and polymorphism by creating a VehicleFleet class that manages vehicles of different types. The VehicleFleet class can use polymorphism to perform operations on objects of different vehicle classes.