Menu
Coddy logo textTech

Abstract Classes and Methods

Part of the Object Oriented Programming section of Coddy's Python journey — lesson 25 of 64.

Abstract classes are classes that cannot be instantiated directly and contain abstract methods that must be implemented by subclasses.

Think of it like a form: An abstract class is like a mandatory form code where some fields are required (abstract methods) and some are optional (concrete methods). You can't submit the form itself - you must fill out all the required fields first. Similarly, you can't create instances of an abstract class until all abstract methods are implemented in a subclass.

Import the abc module to create abstract classes:

from abc import ABC, abstractmethod

Create an abstract class with abstract methods:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Concrete method (has implementation)

The @abstractmethod decorator marks methods that must be implemented by subclasses - these are the "required fields" on your form. Regular methods like describe() can have implementations and are inherited as-is - these are the "pre-filled fields".

Why use abstract classes? They enforce a contract. If you create a Shape class, you're saying "every shape MUST be able to calculate its area and perimeter." This prevents bugs where you might forget to implement critical methods.

Try to create an instance of the abstract class:

# This will cause an error:
# shape = Shape()  # TypeError: Can't instantiate abstract class

This error is intentional - it's like trying to submit an empty form. Python is saying "You haven't filled in the required fields (area and perimeter methods) yet!"

Create a concrete subclass that implements all abstract methods:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

Now we've "filled in all the required fields" - we've implemented both area() and perimeter(). The Circle class is now a complete, concrete class that can be instantiated.

Now you can create instances of the concrete class:

circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe())  # Inherited concrete method

Create another concrete subclass:

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width  self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)

rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())

Output:

78.5
31.400000000000002
This is a shape
24
20

Abstract classes define a contract that subclasses must follow. Use ABC and @abstractmethod to create abstract classes. Subclasses must implement all abstract methods or they'll also be abstract. This ensures consistency and prevents incomplete implementations.

challenge icon

Challenge

Medium

In this challenge, you'll implement a payment processing system.

You need to complete the implementation in these files:

  • paymentmethod.py - Abstract base class with validation logic
  • creditcard.py - Credit card payment implementation
  • paypal.py - PayPal payment implementation

Follow the TODO comments in each file to implement the required functionality. The comments will guide you step-by-step through creating abstract methods, implementing concrete subclasses, and establishing proper import relationships between files.

The driver.py file contains test cases that will verify your implementation works correctly, processing different payment scenarios and displaying appropriate details for each payment method.

Cheat sheet

Abstract classes cannot be instantiated directly and contain abstract methods that must be implemented by subclasses.

Import the abc module:

from abc import ABC, abstractmethod

Create an abstract class with abstract methods:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # Concrete method (has implementation)

The @abstractmethod decorator marks methods that must be implemented by subclasses. Regular methods can have implementations.

Abstract classes cannot be instantiated:

# This will cause an error:
# shape = Shape()  # TypeError: Can't instantiate abstract class

Create concrete subclasses that implement all abstract methods:

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2
    
    def perimeter(self):
        return 2 * 3.14 * self.radius

circle = Circle(5)
print(circle.area())        # 78.5
print(circle.describe())    # Inherited concrete method

Key Point: Abstract classes define a template that subclasses must follow. Subclasses must implement all abstract methods or they'll also be abstract.

Try it yourself

from creditcard import CreditCard
from paypal import PayPal

# Test the implementations - DO NOT MODIFY THIS TEST CODE
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# Process valid payments
if cc.validate(100):
    print(cc.process_payment(100))
    print(cc.payment_details())

if pp.validate(200):
    print(pp.process_payment(200))
    print(pp.payment_details())

# Try an invalid amount
if not pp.validate(0):
    print("Invalid payment amount")

# This would raise an error if uncommented:
# pm = PaymentMethod()  # Can't instantiate abstract class
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming