Skip to main content

Advanced OOP: Magic Methods, Inheritance, and Polymorphism

Introduction

In this tutorial, we are going to delve deeper into Python's advanced object-oriented programming (OOP) concepts - Magic Methods, Inheritance, and Polymorphism. We'll learn what these terms mean, why they're important, and how to use them effectively in your Python code.

Magic Methods

Magic methods in Python are special methods that you can define to add "magic" to your classes. They're always surrounded by double underscores (e.g. __init__ or __str__). These methods provide a simple way to make your classes act like built-in Python types. Let's see how they work in practice.

The __init__ Method

The __init__ method is used for initializing an instance of a class. It's called when a new object of that class is created.

class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed

fido = Dog("Fido", "Labrador")
print(fido.name) # Output: Fido
print(fido.breed) # Output: Labrador

The __str__ Method

The __str__ method in Python represents the class objects as a string. It can be used for classes. The __str__ method should be the most human-readable while __repr__ is meant to be unambiguous.

class Dog:
def __init__(self, name, breed):
self.name = name
self.breed = breed

def __str__(self):
return f'{self.name} is a {self.breed}'

fido = Dog("Fido", "Labrador")
print(fido) # Output: Fido is a Labrador

There are many more magic methods that you can use to customize your classes, like __len__, __del__, __eq__, and so on.

Inheritance

Inheritance is a way of creating new class using details of existing class without modifying it. The newly formed class is a derived class (or child class). Similarly, the existing class is a base class (or parent class).

# Parent class
class Bird:
def __init__(self):
print("Bird is ready")

def whoisThis(self):
print("Bird")

def swim(self):
print("Swim faster")

# Child class
class Penguin(Bird):
def __init__(self):
super().__init__()
print("Penguin is ready")

def whoisThis(self):
print("Penguin")

def run(self):
print("Run faster")

peggy = Penguin()
peggy.whoisThis() # Output: Penguin
peggy.swim() # Output: Swim faster
peggy.run() # Output: Run faster

Polymorphism

Polymorphism is an ability (in OOP) to use a common interface for multiple forms (data types).

Suppose, we need to color a shape, there are multiple shape options (rectangle, square, circle). However we could use the same method to color any shape. This concept is called Polymorphism.

class Parrot:
def fly(self):
print("Parrot can fly")

def swim(self):
print("Parrot can't swim")

class Penguin:
def fly(self):
print("Penguin can't fly")

def swim(self):
print("Penguin can swim")

# common interface
def flying_test(bird):
bird.fly()

# instantiate objects
blu = Parrot()
peggy = Penguin()

# passing the object
flying_test(blu) # Output: Parrot can fly
flying_test(peggy) # Output: Penguin can't fly

In the above program, we defined two classes Parrot and Penguin. Each of them have a common fly() method. However, their functions are different. To allow polymorphism, we created a common interface i.e flying_test() function that can take any object. Then, we passed the objects blu and peggy in the flying_test() function, it ran effectively.

This is how we can use the magic methods, inheritance, and polymorphism in Python. These concepts are crucial for any type of OOP model. With these, you can write more efficient, effective, and easy-to-read codes.