Inheritance and Polymorphism · practice
Use Optional Object Capabilities
A protocol says what every
A choice question may explain its answer. A survey item has nothing useful to explain.
Ask whether a capability exists
Python’s hasattr(object, name) reports whether an attribute or
A report can use the capability when present:
if hasattr(item, "explain"):
lines.append(item.explain())
It still does not ask whether the object is a ChoiceQuestion. A future type can provide explain and receive the same treatment automatically.
Why check for explain rather than checking for ChoiceQuestion?
Keep the core contract small
Optional capabilities are useful only around a solid required protocol. If is_correct were optional, the report could not fulfill its main job.
Use this distinction:
required behavior makes the object usable at all;
optional behavior enriches one use when available.
Do not scatter hasattr around to avoid designing a contract. Use it for genuinely optional additions whose absence has a clear, ordinary meaning.
The exercise starts with the working duck-typed report and adds one optional explanation without naming any concrete class.
Task
Give ChoiceQuestion an explain()
Update report(items, responses) so an item’s explanation appears on its own line immediately after that item’s outcome when, and only when, the explain.
Use hasattr; do not check for a concrete class. The required prompt, points, and is_correct protocol remains unchanged.