3. Polymorphism
The term 'polymorphism' comes from the Greek language and means 'something that takes on multiple forms.'
Polymorphism refers to a subclass's ability to adapt a method that already exists in its superclass to meet its needs. To put it another way, a subclass can use a method from its superclass as is or modify it as needed.
class Academic(Book):
def __init__(self, title, quantity, author, price, branch):
super().__init__(title, quantity, author, price)
self.branch = branch
def __repr__(self):
return f"Book: {self.title}, Branch: {self.branch}, Quantity: {self.quantity}, Author: {self.author}, Price: {self.get_price()}"
The Book superclass has a specific method called repr. This method can be used by subclass Novel so that it is called whenever an object is printed.
The Academic subclass, on the other hand, is defined with its own repr special function in the example code above. The Academic subclass will invoke its own method by suppressing the same method present in its superclass, thanks to polymorphism.
novel1 = Novel('Two States', 20, 'Chetan Bhagat', 200, 187)
novel1.set_discount(0.20)
academic1 = Academic('Python Foundations', 12, 'PSF', 655, 'IT')
print(novel1)
print(academic1)
Output:
Book: Two States, Quantity: 20, Author: Chetan Bhagat, Price: 160.0
Book: Python Foundations, Branch: IT, Quantity: 12, Author: PSF, Price: 655
4. Abstraction
Abstraction isn't supported directly in Python. Calling a magic method, on the other hand, allows for abstraction.
If an abstract method is declared in a superclass, subclasses that inherit from the superclass must have their own implementation of the method.
A superclass's abstract method will never be called by its subclasses. But the abstraction aids in the maintenance of a similar structure across all subclasses.
In our parent class Book, we have defined the repr method. Let's make that method abstract, forcing every subclass to compulsorily have its own repr method.
from abc import ABC, abstractmethod
class Book(ABC):
def __init__(self, title, quantity, author, price):
self.title = title
self.quantity = quantity
self.author = author
self.__price = price
self.__discount = None
def set_discount(self, discount):
self.__discount = discount
def get_price(self):
if self.__discount:
return self.__price * (1-self.__discount)
return self.__price
@abstractmethod
def __repr__(self):
return f"Book: {self.title}, Quantity: {self.quantity}, Author: {self.author}, Price: {self.get_price()}"
class Novel(Book):
def __init__(self, title, quantity, author, price, pages):
super().__init__(title, quantity, author, price)
self.pages = pages
class Academic(Book):
def __init__(self, title, quantity, author, price, branch):
super().__init__(title, quantity, author, price)
self.branch = branch
def __repr__(self):
return f"Book: {self.title}, Branch: {self.branch}, Quantity: {self.quantity}, Author: {self.author}, Price: {self.get_price()}"
novel1 = Novel('Two States', 20, 'Chetan Bhagat', 200, 187)
novel1.set_discount(0.20)
academic1 = Academic('Python Foundations', 12, 'PSF', 655, 'IT')
print(novel1)
print(academic1)
In the above code, we have inherited the ABC class to create the Book class. We've made the repr method abstract by adding the @abstractmethod decorator.
While creating the Novel class, we intentionally missed the implementation of the repr method to see what happens.
Output:
Traceback (most recent call last):
File "C:\Users\ashut\Desktop\Test\hello\test.py", line 40, in <module>
novel1 = Novel('Two States', 20, 'Chetan Bhagat', 200, 187)
TypeError: Can't instantiate abstract class Novel with abstract method __repr__
We get a TypeError saying we cannot instantiate object of the Novel class. Let's add the implementation of the repr method and see what happens now.
class Novel(Book):
def __init__(self, title, quantity, author, price, pages):
super().__init__(title, quantity, author, price)
self.pages = pages
def __repr__(self):
return f"Book: {self.title}, Quantity: {self.quantity}, Author: {self.author}, Price: {self.get_price()}"
Output:
Book: Two States, Quantity: 20, Author: Chetan Bhagat, Price: 160.0
Book: Python Foundations, Branch: IT, Quantity: 12, Author: PSF, Price: 655
Now it works fine.
Method Overloading:
The concept of method overloading is found in almost every well-known programming language that follows object-oriented programming concepts. It simply refers to the use of many methods with the same name that take various numbers of arguments within a single class.
Let's now understand method overloading with the help of the following code:
class OverloadingDemo:
def add(self, x, y):
print(x+y)
def add(self, x, y, z):
print(x+y+z)
obj = OverloadingDemo()
obj.add(2, 3)
Output:
Traceback (most recent call last):
File "C:\Users\ashut\Desktop\Test\hello\setup.py", line 10, in <module>
obj.add(2, 3)
TypeError: add() missing 1 required positional argument: 'z'
You're probably wondering why this happened. As a result, the error is displayed because Python only remembers the most recent definition of add(self, x, y, z), which takes three parameters in addition to self. As a result, three arguments must be passed to the add() method when it is called. To put it another way, it disregards the prior definition of add().
Thus, Python doesn't support Method Overloading by default.
Method Overriding:
When a method with the same name and arguments is used in both a derived class and a base or super class, we say that the derived class method "overrides" the method provided in the base class.
When the overridden method gets called, the derived class's method is always invoked. The method that was used in the base class is now hidden.
class ParentClass:
def call_me(self):
print("I am parent class")
class ChildClass(ParentClass):
def call_me(self):
print("I am child class")
pobj = ParentClass()
pobj.call_me()
cobj = ChildClass()
cobj.call_me()
Output:
I am parent class
I am child class
In the above code, when the call_me() method was called on the child object, the call_me() from the child class was invoked. We can invoke the parent class's call_me() method from the child class using super(), like this:
class ParentClass:
def call_me(self):
print("I am parent class")
class ChildClass(ParentClass):
def call_me(self):
print("I am child class")
super().call_me()
pobj = ParentClass()
pobj.call_me()
cobj = ChildClass()
cobj.call_me()
Output:
I am parent class
I am child class
I am parent class
Wrapping Up:
In this article, we covered what classes and objects mean. We also covered the four pillars of the Object-Oriented Programming.
Apart from that we also touched two important topics – Method Overloading and Method Overriding.
Thanks for reading!
Object-Oriented Programming in Python : Part 1
Top comments (0)