Python Abstract Class vs Concrete Class

I have seen many developers struggle with when to use an abstract class versus a concrete one. It is a common hurdle that can lead to messy, unmaintainable code if you don’t get it right from the start.

I remember working on a large-scale logistics system where we failed to define our base classes properly, and it caused weeks of refactoring.

In this tutorial, I will show you exactly how to distinguish between these two and how to use them effectively in your projects.

What is a Concrete Class?

A concrete class is a regular class that you can use to create objects. It has a complete implementation of all its methods.

In most of your daily coding, you are likely writing concrete classes without even thinking about it.

Think of it like a specific car model on a dealership lot in Detroit; it is a finished product ready to be driven.

What is an Abstract Class?

An abstract class is more like a blueprint or a “template” that cannot be instantiated on its own.

It exists purely to be inherited by other classes, ensuring that they follow a specific structure.

In Python, we use the abc module to define these, marking certain methods as “abstract” to force child classes to implement them.

Method 1: Create a Concrete Class for US Sales Tax

When I build e-commerce tools for US clients, I often start with a concrete class to handle specific state logic.

If you know exactly how a class should behave and you need to create objects from it immediately, a concrete class is the way to go.

Here is how I implement a concrete class for calculating sales tax in Florida:

# A simple concrete class
class FloridaSalesTax:
    def __init__(self, amount):
        self.amount = amount
        self.tax_rate = 0.06  # 6% Florida Sales Tax

    def calculate_total(self):
        return self.amount + (self.amount * self.tax_rate)

# We can create an object directly from this class
order = FloridaSalesTax(100)
print(f"Total price in Florida: ${order.calculate_total()}")

You can refer to the screenshot below to see the output.

Python Abstract Class vs Concrete Class

In this example, the class is “concrete” because every method has a body, and we can instantiate an order without any issues.

Method 2: Use Abstract Classes to Standardize US Shipping

During a project for a national shipping carrier, I realized we needed a way to ensure every shipping method (Ground, Air, Sea) had a consistent interface.

I didn’t want someone to create a “generic” shipping object; I wanted them to use a specific type.

This is where the ABC (Abstract Base Class) and the @abstractmethod decorator become essential.

from abc import ABC, abstractmethod

# Defining the Abstract Base Class
class USPS_Shipping(ABC):
    
    @abstractmethod
    def calculate_shipping_cost(self, weight):
        """This method must be implemented by all subclasses"""
        pass

    def shipping_label_header(self):
        """Concrete method within an abstract class"""
        return "UNITED STATES POSTAL SERVICE - OFFICIAL SHIPMENT"

# Attempting to create an object from an abstract class will raise an error
# carrier = USPS_Shipping()  # This would raise a TypeError

By defining calculate_shipping_cost as an abstract method, I am forcing any developer who uses my code to provide the actual logic for that method.

Method 3: Implement Concrete Subclasses from Abstract Bases

Once you have your abstract blueprint, you create concrete subclasses to do the heavy lifting.

I find this approach incredibly useful when managing different employee types for US-based payroll systems.

Here is the full code showing how an abstract class dictates the rules for concrete implementations:

from abc import ABC, abstractmethod

# Abstract Base Class
class Employee(ABC):
    def __init__(self, name, employee_id):
        self.name = name
        self.employee_id = employee_id

    @abstractmethod
    def calculate_pay(self):
        pass

# Concrete Subclass 1: Salaried Employee
class SalariedEmployee(Employee):
    def __init__(self, name, employee_id, annual_salary):
        super().__init__(name, employee_id)
        self.annual_salary = annual_salary

    def calculate_pay(self):
        return self.annual_salary / 24  # Assuming semi-monthly pay periods

# Concrete Subclass 2: Hourly Employee (California Overtime Logic)
class HourlyEmployee(Employee):
    def __init__(self, name, employee_id, hourly_rate, hours_worked):
        super().__init__(name, employee_id)
        self.hourly_rate = hourly_rate
        self.hours_worked = hours_worked

    def calculate_pay(self):
        # Simplified US hourly logic
        return self.hourly_rate * self.hours_worked

# Implementation in a US Business Context
emp1 = SalariedEmployee("John Doe", "NY-101", 120000)
emp2 = HourlyEmployee("Jane Smith", "CA-202", 50, 40)

print(f"{emp1.name} Paycheck: ${emp1.calculate_pay():.2f}")
print(f"{emp2.name} Paycheck: ${emp2.calculate_pay():.2f}")

You can refer to the screenshot below to see the output.

Abstract Class vs Concrete Class in Python

In this code, Employee provides the structure, but SalariedEmployee and HourlyEmployee provide the actual “concrete” details.

Why Use Abstract Classes? (Firsthand Observations)

I have found that using abstract classes acts as a safeguard for your team.

When I lead a team of developers, I use abstract classes to define the “API” of our internal modules.

It prevents a junior developer from accidentally creating an instance of a class that wasn’t meant to be used on its own.

It also serves as documentation; just by looking at the abstract methods, you know exactly what needs to be coded.

Key Differences at a Glance

To make it easier for you to remember, I’ve summarized the differences based on my experience:

  • Instantiation: You can create objects from concrete classes. You cannot create objects from abstract classes.
  • Purpose: Concrete classes are for specific implementation. Abstract classes are for defining a common interface.
  • Methods: Concrete classes must have all methods implemented. Abstract classes can have both implemented methods and abstract methods.
  • Python Module: You don’t need special modules for concrete classes. Abstract classes require from abc import ABC, abstractmethod.

Common Pitfalls to Avoid

One mistake I made early in my career was making everything abstract.

If you only have one implementation of a class, you probably don’t need an abstract base class.

Over-engineering can make your Python code harder to read and maintain.

I always tell my students: “Start concrete. Only move to abstract when you see a pattern of multiple related classes emerging.”

Handle Multiple Inheritances with Abstract Classes

In complex US financial applications, I sometimes have to inherit from multiple abstract bases.

Python handles this through a concept called Method Resolution Order (MRO).

Ensure that your concrete class satisfies all abstract methods from all parent abstract classes, or it will remain abstract itself.

class Taxable(ABC):
    @abstractmethod
    def get_tax_id(self):
        pass

class Identifiable(ABC):
    @abstractmethod
    def get_legal_name(self):
        pass

class USBusiness(Taxable, Identifiable):
    def get_tax_id(self):
        return "99-9999999" # EIN Example
    
    def get_legal_name(self):
        return "Tech Solutions LLC"

When to Choose One Over the Other

If you are building a tool where you need to represent a generic concept (like “Account” or “Vehicle”), go with an Abstract Class.

If you are representing a specific thing (like “CheckingAccount” or “TeslaModel3”), use a Concrete Class.

I often use abstract classes when I am building frameworks or plugins that other developers will use.

It ensures that their additions will play nicely with the rest of my system.

Performance Considerations

In my experience, there is a negligible performance hit when using abstract classes.

Python’s abc module is highly optimized.

The benefits of code clarity and safety far outweigh any tiny overhead in most US enterprise applications.

I’ve used abstract classes in high-frequency trading scripts and never noticed a bottleneck there.

Understanding the distinction between abstract and concrete classes will significantly improve your Python architecture.

It allows you to write code that is not only functional but also scalable and professional.

I hope this guide helps you decide which one to use in your next project.

You may also like to read:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.