NivaarExam PrepOfficial exam papers ↗

25-Comp-B11 Advanced Software Design · December 2018

Question 26 of 28: Favoring Object Composition Over Class Inheritance, via the Adapter Pattern

Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)

Notes on this paper

17-Comp-B11 Advanced Software Design — National Exams, December 2018. 3 hours, closed book exam with up to 2 aid sheets allowed (written on both sides), no calculator permitted. The paper is organized into five parts, and candidates were instructed to answer any five (5) questions in Part I, any three (3) in Part II, any four (4) in Part III, any two (2) in Part IV, and any five (5) in Part V — only the first questions answered, in each part, as they appear in the answer book are marked. All questions carry equal weight, so the 19 questions actually marked (5+3+4+2+5 of 28) each count for 100/19 ≈ 5.26% of the paper. All 28 questions are answered below for completeness.

Reference texts: Sommerville, Software Engineering (10th ed., Pearson) — software processes, requirements engineering, design principles, dependability; Pressman, Software Engineering: A Practitioner's Approach (9th ed.) — supplementary process and quality coverage; Gamma, Helm, Johnson & Vlissides (GoF), Design Patterns: Elements of Reusable Object-Oriented Software — creational/structural/behavioural pattern catalogue and the "program to an interface, not an implementation" / "favor object composition over class inheritance" principles; Sebesta, Concepts of Programming Languages (12th ed.) — polymorphism, dynamic binding, inheritance and language-level object semantics; Bertrand Meyer, Object-Oriented Software Construction — design by contract, preconditions/postconditions/invariants; Barbara Liskov's 1987 substitutability paper for Question 11; Karl Wiegers, Software Requirements (3rd ed.) — the functional/quality/process/implementation/business requirements taxonomy of Question 2; Kruchten, The Rational Unified Process: An Introduction, for Question 1; Myers, The Art of Software Testing, for Questions 6 and 28.

PART I — General Principles (answer any 5 of 7)

Question 26: Favoring Object Composition Over Class Inheritance, via the Adapter Pattern (Part V)

Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.

Adapter converts the interface of an existing class (the Adaptee) into the interface a client expects (the Target). GoF documents two structurally distinct ways to implement it, illustrating the general composition-vs-inheritance trade-off directly.

Target ClassAdapter Adaptee implements extends Target ObjectAdapter − adaptee: Adaptee implements delegates to
Left: Class Adapter INHERITS Adaptee's implementation directly. Right: Object Adapter COMPOSES a private Adaptee reference and delegates to it.

Class Adapter (inheritance-based). The Adapter INHERITS from Adaptee and implements Target, translating each Target call into the (already-inherited) Adaptee operations. Because it inherits Adaptee's entire implementation, it also inherits, and can be affected by, Adaptee's ENTIRE public/protected interface — the same "message leakage" hazard flagged for Question 11: client code that somehow obtains a reference typed as the concrete ClassAdapter can call inherited Adaptee operations that bypass the adaptation entirely. It is also bound at COMPILE time to exactly one Adaptee class and cannot adapt any of Adaptee's subclasses transparently, since inheritance is a fixed, single relationship chosen once.

Object Adapter (composition-based). The Adapter HOLDS a reference to a separate Adaptee instance and implements Target purely by forwarding each call to it. Only the operations the Adapter explicitly forwards are reachable through the Target interface — nothing of Adaptee's interface leaks through beyond what is deliberately exposed. Because the held reference is typed as Adaptee (or an Adaptee interface), the SAME Object Adapter transparently works with any Adaptee SUBCLASS supplied at construction time, and which concrete Adaptee it wraps can even be changed at runtime.

The principle, illustrated by the diagrams. "Favor object composition over class inheritance" says: when a class needs to reuse another class's behaviour, prefer HOLDING a reference to it (as Object Adapter does) over INHERITING from it (as Class Adapter does), because composition exposes only the deliberately-forwarded operations (no leakage), remains flexible at runtime (any subclass, swappable), and avoids the fragile-base-class coupling of inheriting a whole implementation just to reuse a fraction of it. GoF's own guidance follows this principle directly: it recommends Object Adapter as the DEFAULT choice, reserving Class Adapter for the narrower case where the language and situation make it clearly preferable (e.g. needing to override some of Adaptee's specific behaviour, which requires inheritance).