whenever life put's you in a tough situtation, never say why me! but, try me!

Introduction to Object-Oriented Programming (OOP)

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of objects. It allows for more structured and modular code, making it easier to manage and extend. This module introduces the fundamental concepts of OOP in Python, including classes, objects, and methods, and explains how to use them in your programs.


Subtopic 1: Understanding OOP Concepts

Object-Oriented Programming is based on several core concepts, which include:

  • Encapsulation: The bundling of data and methods that operate on that data within a single unit (class). It helps hide the internal state of objects from the outside world and allows for controlled access to that state through methods (getters and setters).

  • Abstraction: The concept of hiding complex implementation details and providing a simplified interface. In Python, this is often achieved by defining classes and exposing only the essential functionalities.

  • Inheritance: The ability to create a new class that inherits attributes and methods from an existing class. This allows for code reuse and extension of functionality.

  • Polymorphism: The ability of different classes to be treated as instances of the same class through inheritance. It allows methods in different classes to have the same name but behave differently based on the object type.

Example of OOP Concepts:
# Base class
class Animal:
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

# Derived class
class Dog(Animal):
    def speak(self):
        return "Woof!"

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

# Creating objects
dog = Dog()
cat = Cat()

# Using polymorphism
print(dog.speak())  # Output: Woof!
print(cat.speak())  # Output: Meow!

In this example, Dog and Cat inherit from the Animal base class and implement the speak method. The method behaves differently depending on the object.


Subtopic 2: Classes and Objects

A class is a blueprint for creating objects, and an object is an instance of a class. In Python, a class defines the properties and behaviors (methods) that the objects created from it will have.

Defining a Class and Creating Objects
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def display_info(self):
        return f"{self.year} {self.make} {self.model}"

# Creating an object of the class
my_car = Car("Toyota", "Corolla", 2020)

# Accessing object attributes and methods
print(my_car.display_info())  # Output: 2020 Toyota Corolla

In the example above:

  • The class Car has a constructor (__init__ method) that initializes the object with specific attributes.
  • my_car is an object (instance) of the Car class, and we use the display_info() method to retrieve information about it.

Subtopic 3: Instance Variables and Methods

  • Instance Variables: These are variables that are specific to an instance of the class. They are defined inside the __init__ method and are accessed using self.

  • Instance Methods: These are functions defined inside a class that can access or modify instance variables. They take the instance itself (self) as their first argument.

Example of Instance Variables and Methods:
class Dog:
    def __init__(self, name, breed):
        self.name = name  # instance variable
        self.breed = breed  # instance variable

    def bark(self):  # instance method
        return f"{self.name} says Woof!"

# Creating an instance
dog1 = Dog("Buddy", "Golden Retriever")
print(dog1.bark())  # Output: Buddy says Woof!

In this example:

  • name and breed are instance variables.
  • bark() is an instance method that uses the name variable of the object.

Subtopic 4: Class Variables and Methods

  • Class Variables: These are variables that are shared by all instances of the class. They are defined directly inside the class and outside of any methods. Class variables are accessed using the class name or the self keyword.

  • Class Methods: These are methods that are bound to the class and not instances. They take cls as their first argument instead of self, allowing them to modify class-level variables.

Example of Class Variables and Methods:
class Employee:
    raise_amount = 1.04  # class variable

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def apply_raise(self):  # instance method
        self.salary *= self.raise_amount

    @classmethod
    def set_raise_amount(cls, amount):  # class method
        cls.raise_amount = amount

# Creating an instance
emp1 = Employee("John", 50000)
emp1.apply_raise()
print(emp1.salary)  # Output: 52000

# Using class method to change class variable
Employee.set_raise_amount(1.05)
emp2 = Employee("Jane", 60000)
emp2.apply_raise()
print(emp2.salary)  # Output: 63000

In this example:

  • raise_amount is a class variable that is shared by all instances of the Employee class.
  • The class method set_raise_amount() allows us to modify the class variable raise_amount.
  • The instance method apply_raise() uses the raise_amount to adjust the salary of an employee.

Tasks

  1. Task 1: Define a Class for a Book

    • Create a class called Book that represents a book with attributes like title, author, and year_published. Implement methods to display the book's information and to update the publication year.
  2. Task 2: Inheritance

    • Create a class Shape with a method area() and derive two classes from it: Circle and Rectangle. Implement the area() method in both derived classes to calculate the area of the respective shape.
  3. Task 3: Polymorphism

    • Create a base class Shape and two derived classes: Circle and Square. Define a method draw() in each class, and demonstrate polymorphism by calling the draw() method on instances of both classes.
  4. Task 4: Class and Instance Variables

    • Define a class Student with a class variable total_students that keeps track of the total number of student objects created. Each student should have instance variables name and age. Add a method to print the total number of students.
  5. Task 5: Using __str__() Method

    • Implement a __str__() method in the Car class from the previous example to return a string representation of the object that summarizes the car's details.
  6. Task 6: Class Methods and Static Methods

    • Modify the Employee class to include a static method is_working_hours() that returns whether the current time is within working hours (e.g., 9 AM to 5 PM). Call this method without creating an instance of the class.