In simple English,
Abstraction means
Hiding unnecessary details and showing only the important part and also forcing some rules to make sure things work the way they should.
For Example:
Suppose you're using a mobile phone.
You just press the call button to talk to someone.
You don’t think about:
↳ how the signal reaches the tower
↳ how the voice converts to digital data
↳ how the microphone and speaker work inside
All you care about is: "Call is happening."
The rest is hidden → that’s abstraction.
But also, some rules are enforced too.
For example:
If the microphone isn’t working or the SIM card is missing, your phone will not allow you to make a call.
That’s a kind of system rule, like "you must have required components ready" before using the call feature.
Same in code, abstraction not only hides the logic but also forces a rule
Suppose You're Building a Banking App
You have different accounts:
-
SavingsAccount
-
CurrentAccount
-
DigitalWallet
All of them should support:
-
deposit(amount) -
withdraw(amount)
But withdrawal rules will be different for each.
No abstract class yet, just a simple class for an idea:
SavingsAccount
class SavingsAccount:
def deposit(self, amount):
print(f"Deposited {amount}")
def withdraw(self, amount):
print(f"Withdrew {amount}")
DigitalWallet
class DigitalWallet:
def deposit(self, amount):
print(f"Deposited {amount} into wallet")
def withdraw(self, amount):
print(f"Used {amount} from wallet")
Both look fine, right?
Now, in the CurrentAccount class, one dev forgets to write withdraw()?
class CurrentAccount:
def deposit(self, amount):
print(f"Deposited {amount}")
Now what?
acc = CurrentAccount()
acc.withdraw(100) # ❌ This will crash!
So, now you know you need some restriction, meaning some way to enforce the rule, i.e
Every account class must have deposit and withdraw
That’s where the simple class failed, it can’t enforce any subclass to implement a particular method.
And here,
The abstract class came into play.
So, What is an Abstract Class?
An abstract class is a template or blueprint, same a simple class, but it can force rules on every subclass. It means, if it has any abstract method, then it’s a rule.
Every child class must have these abstract methods.
Abstract class can have everything just like a simple class, like
-
properties
-
constructors
-
Have concrete methods (with logic)
-
Have abstract methods (rules only)
Create Abstract Class
Step 1: Import the abc module
from abc import ABC, abstractmethod
abc stands for Abstract Base Classes, it’s a built-in Python module used to define abstract classes and methods.
-
ABCis a class from theabcmodule. -
You inherit from
ABCwhen you want to create an abstract class.
Step 2: Create an Abstract Class
from abc import ABC, abstractmethod
class BankAccount(ABC):
def __init__(self, account_holder):
self.account_holder = account_holder # property
def deposit(self, amount): # Concrete method with logic (internal processing is hidden)
print(f"{self.account_holder} deposited {amount}.")
@abstractmethod
def withdraw(self, amount): # abstract method (rule only)
pass
Here,
-
BankAccountis the abstract class -
self.account_holderis a property -
deposit()is a concrete method (has logic) -
withdraw()is an abstract method → must be implemented by a child class
How do I know withdraw is an abstract method?
If you notice the code:
@abstractmethod
def withdraw(self, amount): # abstract method (rule only)
pass
-
It has
@abstractmethoddecorator on top -
This decorator marks the method as abstract
-
It means → No logic inside, only a rule
-
It tells Python: “Every child class must write its own version of
withdraw()”
Now, any class that inherits BankAccount skips this method → boom! ❌
Python will throw TypeError, saying:
TypeError: Can’t instantiate abstract class…
That’s how abstraction enforces the rule.
Child Class - SavingsAccount
class SavingsAccount(BankAccount):
def __init__(self, account_holder, balance):
super().__init__(account_holder)
self.balance = balance
def withdraw(self, amount): # you must define this
if amount <= self.balance:
self.balance -= amount
print(f"{self.account_holder} withdrew {amount}. Remaining: {self.balance}")
else:
print("Insufficient balance")
Now test it:
acc = SavingsAccount("Maham", 500)
acc.deposit(200)
acc.withdraw(100)
acc.withdraw(700)
Output:
Maham deposited 200.
Maham withdrew 100. Remaining: 600
Insufficient balance
How Abstraction Hides Logic:
-
When a user interacts with a SavingsAccount object and calls
deposit(100), they don’t need to know how thedeposit()function works behind the scenes. -
The logic of processing the deposit is hidden from the user. The user only needs to know that the deposit method will handle the action appropriately based on the account type.
Focusing on Rules:
In the example, the abstract class forces subclasses to implement the withdraw() method, which is a rule. This ensures that every subclass has a withdraw() method, but the specific logic for withdraw() is still hidden and left to the subclass to define.
Abstract + Concrete Together
You can reuse logic in the parent class, and force the child class to only write what's different
class CurrentAccount(BankAccount):
def __init__(self, account_holder, overdraft_limit):
super().__init__(account_holder)
self.overdraft_limit = overdraft_limit
def withdraw(self, amount):
print(f"{self.account_holder} withdrew {amount} using overdraft")
What If You Forget withdraw()
class DigitalWallet(BankAccount):
pass
acc = DigitalWallet("Ali")
Boom:
TypeError: Can't instantiate abstract class DigitalWallet with abstract method withdraw
Its means
You cannot create an object of an abstract class directly without defining the abstract method
Here, DigitalWallet inherited from BankAccount but didn’t define withdraw method so it that’s why it show error.
Can I call the abstract class directly without inheritance?
No, you can’t
An abstract class must be inherited by a subclass before you can use it. You cannot create an object of an abstract class directly. For instance, you can’t directly create a BankAccount class object.
Now, you understand why Abstract Class?
Because
-
To hide the complex logic (e.g., how deposit() is processed, how money is managed within the system).
-
To enforce rules that subclasses must follow (such as implementing withdraw()), while also concealing the internal complexity of the implementation.
-
To prevent the creation of incomplete objects (such as a DigitalWallet without withdraw() logic).
Keeps the project neat.
Summary
Feature | Abstract Class |
|---|---|
Can have logic | ✅ Yes |
Can have properties | ✅ Yes |
Can have only rules | ✅ Yes (abstract methods) |
Can it create an object? | ❌ No |
Purpose | Share code + force rules |