NivaarExam PrepOfficial exam papers ↗

19-Soft-B17 Data Visualization · December 2014

Question 3 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 3 (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.

The Liskov Substitution Principle (LSP) states that if S is declared a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program — correctness, expected behaviour, invariants that client code relies on. Crucially, LSP is a behavioural requirement, not merely a syntactic one: it is not enough for S to inherit or override every method of T with a matching signature (which is all that subclassing in most OO languages actually enforces at compile time); S's methods must also honour every contract — preconditions no stronger, postconditions no weaker, and invariants preserved — that clients of T were entitled to assume. Subclassing therefore gives you subtyping syntactically for free, but it does not automatically give you subtyping behaviourally; the two can diverge whenever the subclass's overridden behaviour surprises code written only against the base class's contract.

RectanglesetWidth(w), setHeight(h)SquaresetWidth/setHeight sync both sidesextendsClient code assumes Rectangle's contract:r.setWidth(5); r.setHeight(4);assert r.area() == 20;If r is really a Square: setHeight(4)also resets width to 4, so area() == 16.Assertion fails — LSP violated.
Fig. Q3 — Square extends Rectangle syntactically, but substituting a Square wherever client code holds a Rectangle reference breaks a postcondition (independent width/height mutation) that the client is entitled to assume.

The canonical counter-example is exactly the one hinted at: a Rectangle class exposes independent setWidth(w) and setHeight(h) mutators, with the implicit invariant/contract that setting one dimension leaves the other unchanged (so area() after setWidth(5); setHeight(4) is always 20, regardless of the order the two setters are called). A Square subclass, to preserve its own geometric invariant that all four sides are equal, must make setWidth also change the height (and vice versa) — there is no other way for a Square instance to stay a valid square after either setter runs. This is a perfectly reasonable design for Square considered in isolation, and Square is syntactically a valid subclass (it compiles, it overrides both methods with matching signatures). But it is not a valid subtype under LSP: any client code written against the Rectangle contract — for instance, code that calls setWidth(5) then setHeight(4) and asserts the resulting area is 20 — will silently get the wrong answer (16) if a Square is substituted for the Rectangle it expected, because setHeight just overwrote the width the client had already set. The subclass has strengthened an invariant (all sides equal) in a way that weakens a postcondition the base class's clients relied on (dimensions set independently), which is exactly the kind of behavioural contract violation LSP forbids. The general lesson is that "is-a" in the everyday sense ("a square is a rectangle," which is true geometrically) does not automatically license "is-a" in the substitutability sense that OO subtyping requires; whether subclassing is safe must be checked against the base class's actual behavioural contract, not against real-world taxonomy.