by Team Codeasify
1381
Table of Contents
What is object-oriented programming(OOPs)?
As the name suggests, programming that is oriented with objects. It sounds cool, but what does it mean?
An object-oriented programming (OOP) is a programming standard that is based on the concept of objects.
Hey that's fine but what is an object? Hope you got an idea about the object.
NOTE: We will use OOPs as object-oriented programming in short form
Let's discuss OOPs in detail.
For example, We have to make a software application in which we have many features like catalog, payment, checkout, authentication and many more. In order to design/model that system through OOPs standards we have to make a collection of objects, where each object represents some particular feature of the system. The characteristics of an object are described by its data (attributes) and behavior (methods).
Wait, Why are we concern about this design and objects?
Okay, so let's discuss about the advantages of the OOPs.
Advantages of OOPs
In software development, object-oriented programming (OOPs) has several advantages:
- Modularity: OOPs allows you to modularize your code, meaning that you can break it down into smaller, independent units (objects) that can be easily reused and maintained. This makes it easier to understand and update your code.
-
Flexibility: In addition to allowing you to extend or modify your code more easily, it also gives you the ability to make new classes that inherit from existing classes some of their attributes and behavior.
-
Reusability: A key advantage of OOPs is the ability to reuse code between different objects, which can save you a lot of time and effort while developing an application.
-
Scalability: OOPs allows you to easily scale your code as your project grows, as you are able to add new objects and functionality as your project grows.
-
Maintainability: OOPs makes it easier to maintain your code. This is because you can make changes to a single class and have those changes automatically reflected in all the objects of that class.
- Readability: The clear and modular structure of OOPs promotes easier reading and understanding of your code.
-
Testability: OOPs makes it easier to test your code, as you can test individual objects and their behavior separately from the rest of the code.
That's great, I want to learn OOPs now.
Okay, Basically we have four main principles of OOPs.
Four main principles of OOPs
In object-oriented programming, we have four main principles/concepts which allow us to achieve all these benefits, and in a nutshell, these four concepts are:
- Encapsulation
-
Abstraction
-
Inheritance
-
Polymorphism
Let's take a closer look at each one of them one by one.
Encapsulation (What is Encapsulation?)
Encapsulation is a concept in object-oriented programming (OOP) that refers to the idea of bundling data and methods that operate on that data within a single unit, or object. Encapsulation allows you to hide the implementation details of a class from other parts of your code. This makes it easier to change or update the implementation without affecting the rest of the code.
In OOP, you can achieve encapsulation through the use of access modifiers, such as public, private, and protected. These modifiers control the visibility and accessibility of class members (attributes and methods) from outside the class.
For example, you might want to mark certain attributes or methods as private. This is because you only want them to be accessible within the class itself, and not from outside the class. This can help prevent other parts of your code from accidentally or intentionally modifying the internal state of the object.
Here's an example of encapsulation in Python using a simple BankAccount class:
class BankAccount:
def __init__(self, balance):
self.__balance = balance # private attribute
def check_balance(self):
return self.__balance
def deposit(self, amount):
self.__balance += amount
def withdraw(self, amount):
if self.__balance >= amount:
self.__balance -= amount
return True
else:
return False
In this example, the BankAccount class has a balance attribute that is marked as private by prefixing it with two underscores (__). This means that the balance attribute can only be accessed or modified from within the BankAccount class, and not from outside the class.
To access or modify the balance attribute from outside the class, you can define public methods like deposit, check_balance, withdraw.
Abstraction (What is Abstraction?)
Abstraction is a concept in object-oriented programming (OOPs) that refers to the idea of exposing only the necessary details of an object to the user, while hiding the implementation details.
Abstraction allows you to focus on what an object does, rather than how it does it.
In OOPs, abstraction can be achieved in several ways:
- Abstract classes: An abstract class is a class that cannot be instantiated (means we can't create an object from that class), but can be subclassed. Abstract classes define a set of abstract methods that must be implemented by any concrete (non-abstract) subclass. Abstract methods are methods that are declared in the abstract class, but do not have an implementation. This allows you to define a common interface for a group of related classes, while leaving the implementation details up to individual subclasses.
-
Interfaces: An interface is a set of abstract methods that define a common set of behaviors that must be implemented by any class that implements the interface. Interfaces are similar to abstract classes, but they cannot have any implementation details and cannot have any attributes.
-
Information hiding: Information hiding is the practice of hiding the implementation details of a class from the user. This can be achieved through the use of access modifiers, such as private and protected, which control the visibility and accessibility of class members (attributes and methods) from outside the class.
A Python abstract class and interface are used here to illustrate abstraction:
from abc import ABC, abstractmethod
class BankAccount(ABC):
@abstractmethod
def deposit(self, amount):
pass
@abstractmethod
def withdraw(self, amount):
pass
@abstractmethod
def check_balance(self):
pass
class SavingsAccount(BankAccount):
def __init__(self, balance):
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return True
else:
return False
def check_balance(self):
return self.balance
class CurrentAccount(BankAccount):
def __init__(self, balance, overdraft_limit):
self.balance = balance
self.overdraft_limit = overdraft_limit
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if self.balance - amount >= -self.overdraft_limit:
self.balance -= amount
return True
else:
return False
def check_balance(self):
return self.balance
In this example, the BankAccount interface defines the abstract methods deposit, withdraw, and check_balance that must be implemented by any class that implements the interface.
The SavingsAccount and CurrentAccount classes both implement the BankAccount interface, meaning they must provide implementations of these abstract methods.
This allows you to define a common interface for different types of bank accounts, while leaving the implementation details up to the individual subclasses.
Inheritance (What is Inheritance?)
Inheritance is a concept in object-oriented programming (OOP) that refers to the ability of a class to inherit the attributes and behaviors of another class. Using inheritance, you can create a new class that is a modified version of an existing class. Classes can be arranged in hierarchies and code can be reused within them.
Python allows inheritance by defining a subclass and specifying the superclass in parentheses after the subclass name. Subclasses inherit all the attributes and behaviors of the superclass, as well as being able to define their own unique attributes and behaviors.
Here's an example of inheritance in Python using a simple BankAccount class and two subclasses: SavingsAccount and CurrentAccount:
class BankAccount:
def __init__(self, balance):
self.balance = balance
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if self.balance >= amount:
self.balance -= amount
return True
else:
return False
def check_balance(self):
return self.balance
class SavingsAccount(BankAccount):
def __init__(self, balance, interest_rate):
super().__init__(balance) # call the superclass constructor
self.interest_rate = interest_rate
def add_interest(self):
self.balance += self.balance * self.interest_rate
class CurrentAccount(BankAccount):
def __init__(self, balance, overdraft_limit):
super().__init__(balance) # call the superclass constructor
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
if self.balance - amount >= -self.overdraft_limit:
self.balance -= amount
return True
else:
return False
In this example, the SavingsAccount and CurrentAccount classes both inherit from the BankAccount superclass.
This means that they both have access to the deposit, withdraw, and check_balance methods of the BankAccount class, as well as their own unique methods: add_interest for SavingsAccount and an overridden withdraw method for CurrentAccount.
Polymorphism (What is Polymorphism?)
In object-oriented programming (OOPs), polymorphism refers to a class's ability to take on multiple forms.
A polymorphic interface (e.g., a method or function) is one that can be implemented by many classes, each having its own implementation. By doing this, you are able to write code that can work with a variety of objects without needing to know what type of object it is working with.
There are several ways to achieve polymorphism in OOPs:
- Method overloading: This is the ability to define multiple methods with the same name, but with different parameters. When the method is called, the correct implementation is chosen based on the number and type of arguments passed to the method.
-
Method overriding: This is the ability to define a method in a subclass that has the same name and parameters as a method in the superclass, but with a different implementation. When the method is called, the subclass implementation is used instead of the superclass
-
Dynamic dispatch: This is the ability to determine at runtime which method to call based on the type of the object being called. This can be achieved through the use of inheritance and method override.
An example of polymorphism in Python might be a bank account system that has a base class called "Account" and two subclasses called "CurrentAccount" and "SavingsAccount".
The Account class might define methods such as "deposit" and "withdraw" that are common to both types of accounts, while the CurrentAccount and SavingsAccount classes might override these methods to implement account-specific behavior, such as calculating and applying fees or interest.
class Account:
def init(self, balance=0):
self.balance = balance
def deposit(self, amount):
self.balance += amount
return self.balance
def withdraw(self, amount):
if amount > self.balance:
raise ValueError("Insufficient funds")
self.balance -= amount
return self.balance
class CurrentAccount(Account):
def init(self, balance=0):
super().init(balance)
self.fee = 0.01
def withdraw(self, amount):
return super().withdraw(amount + self.fee)
class SavingsAccount(Account):
def init(self, balance=0):
super().init(balance)
self.interest_rate = 0.02
def deposit(self, amount):
return super().deposit(amount * (1 + self.interest_rate))
In this example, the CurrentAccount class overrides the withdraw method to apply a fee to the withdrawal amount.
In contrast, the SavingsAccount class overrides the deposit method to apply interest to the deposited amount. These subclasses can be used in the same way as the base Account class, but the methods will behave differently depending on the type of account being used.
For example:
checking_account = CheckingAccount(100)
savings_account = SavingsAccount(100)
checking_account.deposit(50) # returns 150
savings_account.deposit(50) # returns 105
checking_account.withdraw(75) # returns 73.75
savings_account.withdraw(75) # returns 25
In this code, the deposit method for the CurrentAccount class is called with a value of 50, which is added to the account balance and a fee of 0.01 is applied. The deposit method for the SavingsAccount class is called with a value of 50, which is added to the account balance and interest of 0.02 is applied.
The withdraw method for the CurrentAccount class is called with a value of 75, which is subtracted from the account balance and a fee of 0.01 is applied. The withdraw method for the SavingsAccount class is called with a value of 75, which is subtracted from the account balance.
Conclusion
Object-oriented programming (OOP) is a programming paradigm that is based on the concept of objects, which are data structures that contain both data and methods that operate on that data. OOP is designed to make it easier to design and maintain complex software systems by organizing code into reusable objects and by encapsulating the implementation details of those objects.
The four pillars of OOP are inheritance, encapsulation, abstraction, and polymorphism. Inheritance allows you to create a new class that is a modified version of an existing class, and can be used to create a hierarchy of classes and reuse code between them. Encapsulation refers to the idea of bundling data and methods that operate on that data within a single unit, or object, and hiding the implementation details of that object from other parts of the code. Abstraction refers to the idea of exposing only the necessary details of an object to the user, while hiding the implementation details. Polymorphism refers to the ability of a class to take on multiple forms, through method overloading, method overriding, and dynamic dispatch.
OOP has many advantages, including code reuse, modularity, and maintainability. However, it is not the only programming paradigm, and there are other approaches, such as procedural programming and functional programming, that may be better suited for certain tasks. Ultimately, the choice of programming paradigm will depend on the specific needs of the project and the preferences of the programmer.