NivaarExam PrepOfficial exam papers ↗

19-Soft-B17 Data Visualization · December 2014

Question 5 of 10

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

Notes on this paper

04-Soft-B17, Programming Language Paradigm — National Exams, December 2014 (3 hours, open book, 10 questions of equal value, essay-format answers).

Reference texts: Sebesta, Concepts of Programming Languages, 12th ed. (object-oriented language design, subtyping, functional programming, exception handling, lambda expressions); Sommerville, Software Engineering, 10th ed. (object-oriented design, modularity); Gamma et al. (GoF), Design Patterns, 1st ed. (composition-over-inheritance, Liskov Substitution Principle in practice).

Check: this paper's printed course title and all ten questions are exclusively about object-oriented and functional programming-language concepts (classes, subtyping, overriding/overloading, exceptions, functional vs. procedural style, actor model, lambda expressions, immutability) — there is no data-visualization content anywhere in the paper. This solution follows the exam as printed ("04-SOFT-B17: Programming Language Paradigm").

Question 5 (10%)

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.

Object composition builds new functionality by having one object hold a reference to (and delegate work to) one or more other objects — a "has-a" relationship — while inheritance builds new functionality by having a subclass extend a superclass and acquire its interface and implementation automatically — an "is-a" relationship. Composition is the preferable choice in several recurring situations. First, whenever the relationship between two concepts is genuinely "has-a" rather than "is-a": a Car has an Engine, it is not a kind of Engine, so Car should hold an Engine reference rather than extend an Engine class. Using inheritance for a has-a relationship exposes the whole of the "parent's" interface on the child even when most of it is nonsensical for the child, and is a well-known design smell.

Second, composition is preferable when the goal is code reuse without contractual commitment: inheritance forces the subclass to honour the full behavioural contract of the superclass (per the Liskov Substitution Principle discussed above), including contracts that were never intended to be exposed to the subclass's own clients. Composition lets an object reuse another object's implementation internally while presenting its own, independently-designed public interface — the reused object is an implementation detail, not a public commitment. Third, composition avoids the fragile base class problem: because a subclass's implementation is often coupled to internal details of its superclass (through protected members, or through overriding methods the superclass itself calls internally), a seemingly safe change to the superclass can silently break every subclass. An object obtained through composition, by contrast, is used only through its public interface, so it can be changed or even replaced by a different implementation of the same interface without touching the composing class.

Fourth, composition supports run-time flexibility that static inheritance cannot: the composed object (or its interface) can be swapped out while the program is running — this is exactly the mechanism behind the Strategy design pattern, where a class delegates an algorithm to a composed "strategy" object and can be reconfigured with a different strategy at run time, something a compile-time inheritance relationship cannot do. Fifth, composition sidesteps the complications of deep or multiple inheritance hierarchies — diamond-inheritance ambiguities, deep hierarchies that are hard to understand and change, and the temptation to inherit from several classes purely to reuse unrelated pieces of behaviour. The long-standing design guideline "favour composition over inheritance" captures this: inheritance should be reserved for cases where a genuine, LSP-respecting is-a subtyping relationship exists and is expected to remain stable, while composition is the default, lower-risk tool for reusing behaviour in every other case.