Chapter 10 — Teaching Notes

One-line purpose. Teach Fortran's full object model — inheritance, polymorphism, select type, abstract/deferred, finaland the judgment to keep dynamic dispatch out of hot loops, then apply it to an optional abstract solver_t framework.

Key ideas to emphasize

  • type vs class is the hinge. Students conflate them. Drill it: type = monomorphic, compile-time, inlinable, the default; class = polymorphic, run-time dispatch, not inlinable, opt-in. Everything else in the chapter hangs off this distinction.
  • Polymorphism is indirection (the epigraph). Wheeler's line — "another level of indirection… except too many levels" — is the chapter. Dispatch is one level of indirection; used at the coarse grain it is power, sprinkled per-cell it is the "too many levels" that kill performance.
  • The performance rule is non-negotiable (§10.5). Coarse grain (which solver, once per step) = free; fine grain (which cell, per element) = ruinous, because an indirect call can't be inlined and that blocks vectorization. This is the single most important takeaway for the HPC track and returns in Ch. 27.
  • Abstract + deferred = a compiler-enforced contract. Contrast §10.2's zero-returning placeholder (a silent-bug generator) with §10.4's deferred area (a compile error if you forget). This is why abstract types exist, not just how.
  • The "array of boxes" idiom. A polymorphic array is uniform; heterogeneous collections need a wrapper type. This is the #1 thing students get stuck on when they first build a container.

Misconceptions to preempt

  • "class is just a faster/fancier type." (No — it is slower per call; use type by default.)
  • "I can put different shapes in class(shape_t) :: arr(3)." (No — one dynamic type per polymorphic array; use boxes.)
  • "A final procedure takes class(...)." (No — type(...); finalization isn't dispatched.)
  • "I need final to free my allocatable components." (No — they self-deallocate; final is for files, C memory, locks.)
  • "select type is the normal way to handle different types." (Usually a design smell — prefer a deferred binding; select type is for boundaries and genuine one-offs.)
  • "OOP always makes scientific code better." (Only when there's real plural variation and the dispatch is coarse-grained. Otherwise it's overhead — cycles and comprehension.)

A live demonstration (8–10 minutes)

  1. On Compiler Explorer (godbolt.org, gfortran), show a type(circle_t) call to area() — point out it inlines to a couple of instructions. Then change the handle to class(shape_t), allocatable and show the emitted indirect call. Students needn't read assembly fluently; they can see one becomes a jump through a table. That is §10.5, wordless.
  2. Live-build the §10.4 abstract hierarchy from §10.2's placeholder: delete the zero-returning area, add abstract + deferred, then deliberately comment out circle_area's binding and compile — let the class watch the compiler reject it. The error message is the lesson about contracts.

Class-time budget (~75 min for an advanced session)

  • 10 min: extends and overriding; call-the-parent (§10.1).
  • 15 min: type vs class, dynamic dispatch, the box idiom (§10.2) — the core.
  • 10 min: select type and its design-smell warning (§10.3).
  • 15 min: abstract/deferred (the contract) + final (and why you rarely need it) (§10.4).
  • 15 min: when OOP helps/hurts + the hot-loop rule, with the Godbolt demo (§10.5).
  • 10 min: assemble the solver_t framework; place the dispatch (§10.6 + Project Checkpoint).

Prerequisites to review

Chapter 9 (derived types, type-bound procedures, the passed-object dummy, allocatable components) and Chapter 8 (modules, public/private) are mandatory — this chapter is meaningless without them. A 5-minute recap of "a type-bound procedure and how self gets bound" pays for itself. Confirm students remember column-major loop order from Chapter 5 (it justifies keeping the kernel flat).

Connections

Back: Ch. 5 (arrays/column-major), Ch. 6 (intent/passed object), Ch. 8 (modules), Ch. 9 (derived types). Forward: Ch. 11 (pointers — the indirection under polymorphism; allocatable-vs-pointer), Ch. 23 (swap integrators behind an interface), Ch. 24 (the real solver numerics), Ch. 27 (why dispatch is slow — inlining/no-aliasing), Ch. 36 (OOP in real code organization), Ch. 38 (the framework as the capstone seam), Ch. 39 (which spaced-reviews this chapter). The chapter is a natural stopping point for Scientist/HPC tracks to skim §10.3–10.4 and dwell on §10.5–10.6.