An abstract base class marks required methods so a subclass with unresolved abstract methods cannot be instantiated.
Python ABC: prevent construction of an incomplete implementation
Operation contract
The writer interface requires a publish method. An incomplete subclass fails during construction; the local writer implements the operation and returns a receipt identifier. The abstract requirement checks that an implementation exists, not that every accepted input or returned value satisfies the caller’s domain contract.
Failure and ownership boundary
Abstract registration and structural Protocol annotations serve different purposes. A concrete override can still have an incompatible signature or wrong behavior at runtime. Test the collaborator’s accepted values and failures separately; Python Protocol: structural intent without runtime validation and Python unittest.mock: inject a collaborator failure before publication address those obligations.
Working program
from abc import ABC, abstractmethod
class ReceiptWriter(ABC):
@abstractmethod
def publish(self, receipt):
raise NotImplementedError
class MissingWriter(ReceiptWriter):
pass
class LocalReceiptWriter(ReceiptWriter):
def publish(self, receipt):
return receipt["receipt_id"]
try:
MissingWriter()
except TypeError:
print("incomplete writer rejected")
print(LocalReceiptWriter().publish({"receipt_id": "R-0041"}))Output
incomplete writer rejected
R-0041Costs and limits
Abstract method bookkeeping happens during class construction and instantiation checks. Actual method cost is implementation-dependent. The fixture performs no storage publication despite its interface name; its writer returns a local value only.
Common Mistakes
- A concrete override is not proof of behavioral compatibility.
- Do not confuse an ABC with payload validation.
Connected lessons
Python Protocol: structural intent without runtime validation, Python unittest.mock: inject a collaborator failure before publication, Python metaclasses: validate a class before registering its wire format.
