Self-Assessment Quiz: Object-Oriented Fortran

Twenty questions on the mechanics and the judgment. This is an advanced chapter; aim for 16 or more. Answers and a topic map are at the end — try the whole quiz first, and predict the code outputs by hand.


Question 1

type, extends(shape_t) :: circle_t makes circle_t: - A. A copy of shape_t with a different name - B. A type that inherits shape_t's components and bindings and may add or override - C. A pointer to a shape_t - D. An alias for shape_t

Question 2

The difference between type(shape_t) and class(shape_t) is: - A. None; they are synonyms - B. type is monomorphic (fixed type); class is polymorphic (may hold the type or any extension) - C. class is faster - D. type allows inheritance; class does not

Question 3

A polymorphic local variable class(shape_t) :: s (not a dummy argument) is: - A. Always allowed - B. Allowed only if it is allocatable or pointer - C. Allowed only for abstract types - D. Never allowed under any circumstances

Question 4

In select type, type is (circle_t) matches when the dynamic type is: - A. circle_t or any extension of it - B. Exactly circle_t - C. Any shape - D. shape_t only

Question 5

class is (rectangle_t) matches when the dynamic type is: - A. Exactly rectangle_t - B. rectangle_t or any type that extends it - C. Any type at all - D. Only abstract types

Question 6

An abstract type: - A. Can be instantiated with type(...) - B. Cannot be instantiated; it exists only to be extended - C. Cannot have components - D. Cannot be extended

Question 7

A deferred binding: - A. Provides a default implementation - B. Names a binding with no body that every concrete extension must implement - C. Is called only at program exit - D. Is a synonym for final

Question 8

Inside an abstract interface body, you must import the host's derived types because: - A. import is faster than use - B. The interface body is a separate scoping unit and does not automatically see host entities - C. Abstract types cannot be named - D. It is optional stylistic sugar

Question 9

A final procedure's dummy argument must be declared: - A. class(t), intent(inout) - B. type(t), intent(inout) - C. class(t), intent(in) - D. type(t), intent(out)

Question 10

A final procedure runs: - A. When you call it explicitly - B. Automatically, just before an object of its type is destroyed - C. Only for pointer variables - D. At the start of every procedure

Question 11

To store a mix of circle_t and rectangle_t values in one array, you should: - A. Use class(shape_t), allocatable :: arr(:) - B. Use an array of a small derived type that wraps class(shape_t), allocatable :: obj - C. Use type(shape_t) :: arr(:) - D. It is impossible in Fortran

Question 12

Why can't class(shape_t), allocatable :: arr(:) hold a mix of dynamic types? - A. Arrays cannot be allocatable - B. Every element of a polymorphic array must share one dynamic type - C. class is not allowed for arrays - D. It can — the premise is false

Question 13

The single most important performance rule of this chapter is: - A. Always use class instead of type - B. Put polymorphism at the coarse grain (which solver), never in the hot inner loop (per cell) - C. Never use modules with OOP - D. Finalize every object manually

Question 14

A dynamically dispatched call is often slower mainly because: - A. It uses more memory - B. It cannot be inlined, which blocks the optimizer from fusing and vectorizing the call - C. It runs on the GPU - D. It allocates a new object each time

Question 15

Calling the parent's version of an overridden binding from a child is written: - A. call super%method() - B. call self%parent_t%method() (via the parent component) - C. call parent::method() - D. call method@parent()

Question 16

A long select type chain that implements different behavior per type is usually a sign that: - A. Your code is well designed - B. You should have used a deferred binding so each type carries its own behavior - C. You need more class default blocks - D. Polymorphism is impossible here

Question 17

Object orientation arrived in which Fortran standard? - A. FORTRAN 77 - B. Fortran 95 - C. Fortran 2003 - D. Fortran 2018

Question 18 (what does it print?)

Using the abstract hierarchy, with a rectangle of width 3 and height 4:

class(shape_t), allocatable :: s
allocate(s, source = rectangle_t(width = 3.0_dp, height = 4.0_dp))
print '(f6.2)', s%area()
  • A. 12.00
  • B. 0.00
  • C. A compile error
  • D. 7.00

Question 19 (true/false + justify)

True or false: "Because allocatable components are deallocated automatically when their containing object is destroyed, you usually do not need a final procedure to free them."

Question 20 (short answer)

In the solver_t framework, the driver holds a class(solver_t) and calls sim%step(plate) once per timestep. State (a) where the dynamic dispatch happens and (b) why placing it there, rather than inside the per-cell loop, is the correct design.


Answer Key

Q Ans Why
1 B extends inherits components and bindings; the child may add and override.
2 B type is monomorphic; class is polymorphic (declared vs dynamic type may differ).
3 B A polymorphic non-dummy object needs indirection: allocatable or pointer.
4 B type is matches the exact dynamic type.
5 B class is matches that type or any extension.
6 B Abstract types cannot be instantiated; they are extended.
7 B A deferred binding is a contract every concrete extension must fulfill.
8 B The interface body is its own scoping unit; import brings host names in.
9 B A finalizer takes type(...), intent(inout) — it is not dispatched.
10 B It runs automatically just before destruction (deallocate/scope exit/overwrite).
11 B Wrap the polymorphic value in a box type and make an array of boxes.
12 B A polymorphic array is uniform: one dynamic type for all elements.
13 B Coarse-grained polymorphism only; never dispatch per cell in a hot loop.
14 B An indirect call can't be inlined, which blocks fusion and vectorization.
15 B Reach the parent through the parent component: self%parent_t%method().
16 B Per-type behavior belongs in a deferred binding, not a maintained chain.
17 C Fortran 2003 made the language object-oriented.
18 A rectangle_area returns $3\times4=12$; f6.2 prints 12.00.
19 True Allocatable components self-deallocate; final is for unmanaged resources (files, C memory).
20 (a) At sim%step — one dispatch per timestep. (b) It is amortized over the whole grid update, so it costs nothing, while the per-cell arithmetic stays monomorphic, inlinable, and vectorizable.

Topics to review by question

  • Q1, Q15 → §10.1 (type extension, calling the parent).
  • Q2, Q3, Q11, Q12 → §10.2 (class vs type, polymorphic arrays and the box idiom).
  • Q4, Q5, Q16 → §10.3 (select type; the design-smell warning).
  • Q6–Q10, Q19 → §10.4 (abstract, deferred, import, final).
  • Q13, Q14, Q20 → §10.5 and §10.6 (when OOP hurts; keep dispatch coarse-grained).
  • Q17 → §10.1 (from history: OOP in Fortran 2003).
  • Q18 → §10.4 (dispatch through an abstract type).

Scored below 16? Re-read §10.2 (the class/type distinction and the box idiom) and §10.5 (the performance rule) — those two carry the chapter, and both return in Part VII and Part VIII.