Inheritance, composition and _privacy

Share a reporter; put the difference in a field or a subtype. Has-a (a lab has a sensor) is often simpler than is-a. _name is a convention: please do not touch from outside.

Campus lab board

Utilisation is used ÷ seats.

You will be able to

  • Share one report() across device types instead of copying the line
  • Prefer has-a (a lab holds a sensor) when is-a would only add a field
  • Treat _name as a convention: please do not touch from outside

Gate sensors and lab sensors both report celsius

The report line is the same; the device name differs. Share report(dev). Copy-paste of the print into six files is how one file gets “Celcius” and five do not. Inheritance on a laptop is this idea with extra syntax: a base type that knows how to report, and subtypes that fill in id and source. You do not need that syntax to practise the design.

When the difference is only a string ("gate" vs "lab"), a field is enough. When the difference is behaviour (USB vs Wi-Fi read), you will want two functions or two classes. Do not build a class tree because a diagram looked busy — build it when two callers were about to copy a formula.

Has-a is often simpler than is-a; _privacy is a please

A lab bench has a sensor: lab["sensor"]["c"]. That is composition — a record inside a record. Inheritance says a LabSensor is-a Sensor. Has-a is usually the campus default. _raw on a dict (or _raw on a laptop instance) means “implementation leftover; outside code should call report().” It is a convention, not a lock. Double underscore name-mangling on a laptop is still not security; it is a hint against accidental clashes.

Reuse the contract, not the pygame colour. report returns a string. The kiosk prints it. The log file writes it.

Laptop: subclass, composition, _privacy

class Sensor:
    def __init__(self, id, c):
        self.id = id
        self._raw = c

    def report(self):
        return f"{self.id}: {self._raw} C"

class LabSensor(Sensor):
    pass

lab = {"id": "BENCH-1", "sensor": LabSensor("DHT-04", 31)}
print(lab["sensor"].report())

Words that matter

Inheritance
A laptop feature: a type that extends another type’s behaviour.
Composition
A record that contains another record — has-a.
_name
Convention: please do not use from outside; call the public function.

Common mistakes

Avoid: Six copied report lines with six spellings of celsius.

Do this: One report(device) every screen calls.

Run it step by step

Each box is a real program. Press Run, change a number, Run again — the output must follow your code.

1. Step 1 — one reporter

Change the unit in one function. Both devices follow.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

2. Step 2 — composition plus a private field

Lab has a sensor. Outside code uses report, not _raw.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Example program — Difference in a field, not a second reporter

kind is data. One report.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Your turn — Shared line

report(name, c) returns a string with both the name and C. Print report("Lab", 30) so Lab and 30 appear.

Python sandboxlesson://workspace
console

Edit the example, press Run, then Build if you want a compile check.

build

Press Build to compile.

Self-assessment

Check your understanding before you mark the lesson complete.

1. Share behaviour when…
2. If two devices differ only by id, prefer…

Progress is stored in a browser cookie on this device.