Skip to main content

Chapter 59: Inheritance, Composition, and Design

In Chapter 58, James built a Note class with __init__, summarize, add_tag, remove_tag, has_tag, and a computed word_count. Twelve tests. All green. Now he needs three kinds of notes (text, code, link) and a collection to hold them. Two design patterns solve this: inheritance (when one type is a specialized version of another) and composition (when one object contains another). This chapter teaches you when to use each, how to spot inheritance gone wrong, and how to make the decision repeatable.

The TDG connection: same cycle, but now you design class hierarchies instead of single classes. "Specify" means defining parent and child class interfaces with typed method signatures. "Test" means verifying both inherited and specialized behavior across multiple classes. The loop is the same. The architecture is bigger.

What You Will Learn

By the end of this chapter, you will be able to:

  • Create subclasses that inherit parent behavior and override specific methods to specialize, using super().__init__() to reuse parent initialization
  • Identify the fragile base class problem, evaluate hierarchy depth, and apply the is-a vs uses test to detect bad inheritance
  • Build classes using composition (has-a) with delegation methods that expose only the interface you choose
  • Apply a one-question design decision framework to classify any class relationship as inheritance or composition
  • Enforce contracts with ABC and @abstractmethod, and preview Protocol for structural subtyping
  • Build the complete SmartNotes hierarchy from scratch using TDG with 15+ tests

Chapter Lessons

LessonTitleWhat You DoDuration
1InheritanceCreate TextNote(Note) and CodeNote(Note) subclasses. Override methods. Use super().init() to reuse parent validation.20 min
2The Inheritance TrapBreak a hierarchy by changing the parent. See the fragile base class problem, the diamond problem, and wrong is-a relationships.15 min
3CompositionBuild NoteCollection with a private list attribute and delegation. Build TagManager wrapping a dict. Assemble SmartNotesApp from independent components.20 min
4The Design Decision FrameworkApply one question to five SmartNotes relationships. Use ABC and @abstractmethod to enforce contracts. Preview Protocol.15 min
5SmartNotes Hierarchy TDGBuild TextNote, CodeNote, LinkNote, and NoteCollection from scratch: design decisions, stubs, 15+ tests, AI generation, verification stack.25 min
6Chapter 59 Quiz20 scenario-based questions covering all five lessons25 min

PRIMM-AI+ in This Chapter

Every lesson includes a PRIMM-AI+ Practice section following the five-stage cycle from Chapter 42. This is Phase 5: the TDG cycle now specifies class hierarchies (parent/child relationships and composed components) instead of single classes.

StageWhat You DoClaude Code Tool
Predict [AI-FREE]Predict which class's method runs, whether changing a parent breaks children, or whether a class should use inheritance or composition. Press Shift+Tab for Plan Mode.Plan Mode protects prediction
RunPress Shift+Tab to exit Plan Mode. Run uv run pytest on hierarchy tests, uv run pyright on class stubs, or uv run python to observe method resolution and delegation behavior.You run it, not Claude Code
InvestigateRead failure output or class behavior to understand why a prediction was wrong. In Claude Code, type: /investigate for Socratic questions about inheritance, composition, and method resolution./investigate probes mechanics
ModifyRefine a class hierarchy, fix a broken super() call, or refactor inheritance to composition. Predict whether the change resolves the issue.You edit, Claude Code reviews
Make [Mastery Gate]Build the complete SmartNotes hierarchy from scratch with the TDG cycle: design decisions, stubs, 15+ tests, AI generation, and verification./tdg, /bug, /debug guide the cycle
Starter Kit

Your PRIMM-AI+ starter kit from Chapter 42 works throughout Phase 5. Use /predict, /investigate, /bug, /debug, and /tdg commands as you work through each lesson.

Prerequisites

Before starting this chapter, you should be able to:

  • Write a Python class with __init__, typed methods, and instance attributes using self (Chapter 58)
  • Distinguish between instance attributes and class attributes, and avoid the mutable class attribute trap (Chapter 58, Lesson 4)
  • Drive the full TDG cycle independently: specify, test, generate, verify, debug (Chapter 57)
  • Write and run pytest tests using uv run pytest (Chapters 46, 52)
  • Run the verification tools: uv run ruff check, uv run pyright, uv run pytest (Chapters 52-56)

The SmartNotes Connection

This chapter extends the SmartNotes Note class from Chapter 58 into a full class hierarchy. The single Note class becomes a family:

  • TextNote(Note): inherits everything, overrides summarize() with a [TEXT] prefix
  • CodeNote(Note): inherits everything, adds a language attribute, overrides summarize() with the language tag
  • LinkNote(Note): inherits everything, adds a url attribute, overrides summarize() with the URL
  • NoteCollection: uses composition to contain a list[Note] and expose only add, count, search_by_tag, and summarize_all

The five lessons mirror the journey from single class to hierarchy:

  • Lesson 1 (Inheritance): Create specialized note types that reuse the parent's validated initialization
  • Lesson 2 (The Trap): See what breaks when the parent changes and learn when inheritance is wrong
  • Lesson 3 (Composition): Build containers that control their own interface through delegation
  • Lesson 4 (The Framework): A repeatable one-question decision process for any class relationship
  • Lesson 5 (Capstone): Build the entire hierarchy from scratch using TDG with 15+ tests