Till now, you’ve understood what an abstract class is, right? Just keep it in mind.
Simply put, it’s a class that can:
-
have both concrete and abstract methods
-
maybe even some properties
Concrete Method = Properly defined + Has some working logic
Abstract Method = Defined, but no body → subclass has to give the logic
So basically, an abstract class can have a mix of both, some logic and some rules.
And haan, remember, you cannot create an object of an abstract class directly.
I mean, suppose you're working on a banking app. Let’s take a banking example:
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
print(f"{self.account_holder} deposited {amount}.")
@abstractmethod # abstract method
def withdraw(self, amount):
pass
-
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 child class
Now, any class that inherits BankAccount must define withdraw()
If not, Python will shout: “TypeError: Can’t instantiate abstract class…”
Example: Savings Account
class SavingsAccount(BankAccount):
def __init__(self, account_holder, balance):
super().__init__(account_holder)
self.balance = balance
def withdraw(self, amount): # implementing abstract method
if amount <= self.balance:
self.balance -= amount
print(f"{self.account_holder} withdrew {amount}. Remaining balance: {self.balance}")
else:
print("Insufficient balance.")
Use it like this:
account = SavingsAccount("John", 500)
account.deposit(200) # John deposited 200
account.withdraw(100) # John withdrew 100. Remaining balance: 600
account.withdraw(700) # Insufficient balance.
But did you notice?
We had:
-
properties
-
a concrete method
deposit()
So this BankAccount an abstract class is not fully rules only, right?
If any child class inherits, they don’t need to define deposit(), because it’s already there.
What If I Want Just Rules, No Logic?
Now suppose you’re still designing the banking app. You want to create only a rulebook.
For example, you want to say:
-
Every account must have a
deposit()method -
Every account must have a
withdraw()method -
But how they write it, I don’t care
No logic, no properties, just rules.
That’s where an interface-style class comes in.
What’s an Interface?
I mean, simply:
-
It’s like a rulebook or contract
-
It says: “If you inherit me, you must follow my rules!”
Python doesn’t have real interfaces like Java, but we can fake it using abstract classes, just don’t write any logic or properties in it.
Interface in Code
from abc import ABC, abstractmethod
class BankAccount(ABC):
@abstractmethod
def deposit(self, amount):
pass
@abstractmethod
def withdraw(self, amount):
pass
Now, if you create a class that wants to be a BankAccount, it must define both methods.
Real Implementation
class SavingsAccount(BankAccount):
def __init__(self):
self.balance = 0
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
if amount <= self.balance:
self.balance -= amount
Try using it:
acc = SavingsAccount()
acc.deposit(1000)
acc.withdraw(200)
print(acc.balance) # Output: 800
What If You Forget to Follow the Rule?
class DigitalWallet(BankAccount):
def deposit(self, amount):
self.balance += amount
Boom! Python will scream:
TypeError: Can't instantiate abstract class DigitalWallet with abstract method withdraw
Because you broke the contract.
Why Use Interface-Style Classes?
-
When multiple developers are working together
(Everyone knows which methods to write) -
Keeps things consistent
(Structure stays the same even if logic is different) -
Avoids silly mistakes
(Forces devs to follow rules)
Real-Life Example: Payment System
Let’s say you’re building a payment system.
You’ll have different payment methods, PayPal, Bank Transfer, etc.
All of them should have a pay() method, right?
So, make an interface-style class:
from abc import ABC, abstractmethod
class PaymentMethod(ABC):
@abstractmethod
def pay(self, amount):
pass
Then make different payment classes:
class Paypal(PaymentMethod):
def pay(self, amount):
print(f"Paid {amount} using Paypal")
class BankTransfer(PaymentMethod):
def pay(self, amount):
print(f"Paid {amount} using Bank Transfer")
Now you can use them like this:
def make_payment(method: PaymentMethod, amount):
method.pay(amount)
make_payment(Paypal(), 500)
make_payment(BankTransfer(), 300)
Doesn’t matter how it’s done, as long as pay() exists.
Summary
-
Interface = Just a rulebook
-
Only says what methods should exist, not how
-
No logic, no properties
-
Forces structure
-
Super useful in team projects