What an abstract class is
Sometimes you want to describe what a whole family of classes can do without committing to how. Every animal can speak(), but how depends on whether it is a dog or a cat. An abstract class captures that: it is a half-finished template that you cannot instantiate directly. It declares methods with no real implementation, called abstract methods, and every concrete subclass must supply them.
That gives an abstract class two properties:
- You cannot create an object of the abstract class itself. You must pick a concrete subclass.
- A subclass that leaves any abstract method unimplemented cannot be instantiated either. The abstract class is a contract that Python actually checks.
The syntax in Python
Python's tools live in the abc module. The class inherits from ABC, and each abstract method gets the @abstractmethod decorator:
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self): pass
class Dog(Animal):
def speak(self):
print("Woof")
The body of an abstract method is usually just pass, since the subclasses provide the real code. Now try to break the contract:
class Lazy(Animal):
pass
Animal()
Lazy()
TypeError: Can't instantiate abstract class Animal without an implementation for abstract method 'speak'
The first line raises the error shown above. Lazy() would raise the same kind of TypeError for its own name, since Lazy never implemented speak. Python stops at creation time, before any method is called, so the mistake shows up early.
Mixing abstract and concrete methods
An abstract class may also contain ordinary methods with bodies and ordinary attributes. Subclasses inherit them as usual, and only the methods marked abstract must be overridden. Concrete methods can even call the abstract ones, relying on the subclass to fill them in:
class Animal(ABC):
@abstractmethod
def speak(self): pass
def intro(self):
print("I say:")
self.speak()
Dog().intro()
I say:
Woof
Here intro is written once in Animal and works for every subclass, each producing its own sound. That is polymorphism combined with shared code.
The ABC base matters
The decorator alone does nothing. A class that does not inherit from ABC can use @abstractmethod without any error, and its objects can still be created. Both parts are required for Python to enforce the contract.
The lesson's exercise
The starter code already holds the abstract Animal and, at the bottom, rex = Dog() followed by rex.speak(). The Dog class is missing, so the program would fail with a NameError.
- Declare the concrete subclass. Write
class Dog(Animal):belowAnimal. Python cannot createAnimalobjects, so the program needs a class it can instantiate. - Implement the abstract method. Inside
Dog, writedef speak(self):withprint("Woof")in its body. If you skip this,Dog()raises the sameTypeErrorasAnimal(), because the abstract method is still unimplemented.
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self): pass
class Dog(Animal):
def speak(self):
print("Woof")
rex = Dog()
rex.speak()
Woof
Common mistakes
- Misspelling the method name. Defining
SpeakorspeekinDogleavesspeakabstract, soDog()still fails. - Forgetting the base class. Without
ABC,Animal()is accepted silently and no contract exists. - Instantiating the abstract class.
Animal()is an error by design. Create a concrete subclass instead. - Expecting a missing implementation to fail only when called. The error comes when the object is created.
Abstract classes in other languages
Java and C# use an abstract keyword on both the class and the method. C++ marks a method with = 0, making it pure virtual. JavaScript has no built-in support, and the usual substitute is a parent method that throws an error. Python sits in the middle: the check exists, but it comes from a library module rather than a keyword.
Key takeaways
- An abstract class is a template that cannot be instantiated.
- In Python, inherit from
abc.ABCand mark methods with@abstractmethod. - A subclass must implement every abstract method before it can be instantiated.
- Abstract classes can mix required methods with ordinary shared ones.