Abstract Class

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.

  • ABC is a class from the abc module.

  • You inherit from ABC when 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,

  • BankAccount is the abstract class

  • self.account_holder is 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 @abstractmethod decorator 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 the deposit() 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

Updated on