18 — Practice solutions
These are independently written explanations, not an official marking scheme.
18A
Workout: date (string/date representation as specified), duration (number), summary() → str. Cardio inherits Workout and adds distance (number), overriding summary() → str. Strength inherits Workout and adds repetitions (integer), also overriding summary. A loop calling each workout’s summary can display distance for Cardio and repetitions for Strength while using the same method name.
classDiagram Workout <|-- Cardio Workout <|-- Strength class Workout { +str date +float duration +summary() str } class Cardio { +float distance +summary() str } class Strength { +int repetitions +summary() str }
Reasoning
Date and duration apply to all workouts; distance and repetitions distinguish specialised types. Both specialised objects are workouts, giving an inheritance relationship. A polymorphism example must show how one
summary()call produces type-appropriate content, rather than merely using a common method name.
18B
class Device:
def __init__(self, device_id):
self.device_id = device_id
self.is_on = False
def activate(self):
self.is_on = True
class Camera(Device):
def __init__(self, device_id):
super().__init__(device_id)
self.recording = False
def activate(self):
super().activate() # Preserve the inherited switch-on behaviour.
self.recording = True # Add camera-specific activation behaviour.
class SmartCamera(Camera):
passAfter camera = SmartCamera("C1"), is_on and recording are False. After camera.activate(), both are True. This simplified question gives SmartCamera no additional state; it inherits Camera’s behaviour. The original paper has further details to model.
Reasoning
A SmartCamera is a Camera and a Camera is a Device. Camera adds recording state but still needs the inherited device ID/on-off state. Its activation must do both jobs, so invoke the base activation and then add recording behaviour. No extra SmartCamera attribute was specified in this adapted question.
18C
Insert this method inside Account (same indentation as deposit):
def withdraw(self, amount):
if amount <= 0 or amount > self.__balance: # Validate before mutating state.
return False
self.__balance -= amount
return TrueThe method provides a controlled interface and keeps validation with the state change. A withdrawal exactly equal to the balance succeeds and leaves zero; an unsuccessful withdrawal leaves the previous balance intact.
Reasoning
Unsuccessful withdrawals must leave balance unchanged, so both rejection conditions precede subtraction. Equality with balance is valid: only an amount greater than balance fails. The method returns a Boolean, not the updated balance.