5: Object-Oriented Programming (OOP)
5.1 What is Object-Oriented Programming?
Object-Oriented Programming (OOP) is a programming paradigm that organizes code around objects instead of functions and logic. In OOP, everything is modeled as an object, which represents a real-world entity. Think of objects as a Car
, a Dog
, or a User
.
Each object has two main characteristics:
- Attributes: The properties or characteristics of the object. (E.g., for a
Car
:color
,brand
,speed
). - Methods: The actions that the object can perform. (E.g., for a
Car
:accelerate()
,brake()
,start()
).
OOP is based on four pillars:
- Inheritance: Allows a class (child) to inherit attributes and methods from another class (parent).
- Polymorphism: Allows the same method to behave differently in different classes.
- Encapsulation: Groups the data and the methods that manipulate it into a single unit (the class), and protects them from external modification.
- Abstraction: Shows only the relevant details of the object to the user, hiding its internal complexity.
5.2 Classes and Objects
A class is like a "blueprint" or template for creating objects. It defines the attributes and methods that the objects created from it will have. An object is an instance of a class.
Defining a class
To define a class, we use the keyword class
. Class names are usually written with the first letter capitalized (CamelCase
).
class Car:
# The __init__ method is the constructor
def __init__(self, brand, color):
self.brand = brand
self.color = color
# A method of the class
def accelerate(self):
print(f"The car {self.brand} is accelerating.")
The __init__
method is special; it is known as the constructor. It runs automatically when you create a new object. The first parameter, self
, is a reference to the object being created. Attributes defined with self.
(e.g., self.brand
) belong to the object.
Creating objects (instances)
To create an object from the class, simply call the class name as if it were a function.
# Create two objects from the Car class
car1 = Car("Ford", "red")
car2 = Car("Tesla", "black")
# Access object attributes
print(car1.color) # Output: red
# Call an object method
car2.accelerate() # Output: The car Tesla is accelerating.
5.3 Inheritance and Polymorphism
Inheritance
Inheritance allows us to create a new class (child class) that reuses the attributes and methods of an existing class (parent class). This is useful for modeling "is a" relationships. For example, an ElectricCar
is a type of Car
.
# Parent class
class Vehicle:
def __init__(self, brand):
self.brand = brand
def describe(self):
print(f"This is a vehicle of brand {self.brand}.")
# Child class that inherits from Vehicle
class Car(Vehicle):
def __init__(self, brand, color):
# Call the constructor of the parent class
super().__init__(brand)
self.color = color
def describe(self):
print(f"This is a car of brand {self.brand} and color {self.color}.")
tesla_car = Car("Tesla", "gray")
tesla_car.describe() # Output: This is a car of brand Tesla and color gray.
The super()
function is used to call a method from the parent class, in this case, its constructor.
Polymorphism
Polymorphism means that objects of different classes can respond to the same method call in different ways. In the example above, the child class Car
overrides the describe()
method of the parent class Vehicle
to adapt it to its own functionality.
# Create objects from different classes
generic_vehicle = Vehicle("Generic")
tesla_car = Car("Tesla", "gray")
generic_vehicle.describe() # Output: This is a vehicle of brand Generic.
tesla_car.describe() # Output: This is a car of brand Tesla and color gray.
Both objects have a describe()
method, but the behavior is different for each. That’s polymorphism in action!
OOP provides you with a powerful set of tools to build robust and well-structured applications. In the next module, we’ll explore how to organize your code into files and packages for larger projects.