@@ -58,31 +58,29 @@ The industry has been quietly walking back from "everything is an object" and fr
5858## The Liskov Substitution Principle {#liskov-substitution}
5959
6060The * Liskov Substitution Principle* (LSP)
61- says that an object of a subtype must work anywhere code expects an object of its base type,
62- without breaking the program.
63- A subclass may add behavior, but it must honor the base class's contract.
61+ says that an object of a subtype must work anywhere code expects an object of its base type.
62+ A subclass may add behavior, but it must honor the base class contract.
6463It accepts the same arguments, returns the same kinds of results,
6564and raises no surprising exceptions.
6665When subclasses obey it,
6766code written against the base class works unchanged on any of them.
6867This is what makes polymorphism,
6968and patterns like the [ Template Method] ( 25_Template_Method.md ) , safe.
70- A statically typed compiler can check part of it,
71- that an override's signature stays compatible,
72- but not whether the override actually behaves the way the base class promises.
69+ A statically typed compiler can check that an override's signature stays compatible.
70+ It cannot check whether the override actually behaves the way the base class promises.
7371The base class calls a method and trusts every subclass to stand in for it.
7472
75- Python has no compiler to enforce even that structural check.
76- Nothing stops a subclass from breaking the base class's contract.
73+ Python has no compiler to enforce that structural check.
74+ Nothing stops a subclass from breaking the base class contract.
7775The interpreter runs code that violates the LSP without objection.
7876That code may or may not fail at run time.
7977
8078## Encapsulation Leaks
8179
8280The first OOP promise is encapsulation: hide the data,
8381expose it only through methods you control.
84- In Python the usual move is a leading underscore and a read-only property.
85- It does not work as well as it looks.
82+ Python hides a field with a leading underscore and a read-only property.
83+ This does not work as well as it looks.
8684A getter that returns a mutable object hands the caller a reference to the underlying internals:
8785
8886``` python
@@ -125,19 +123,6 @@ the identical object the underscore was hiding.
125123Python's ` return ` hands out references, never copies.
126124The property blocked reassigning ` numbers ` ,
127125but it could not stop the caller from mutating the list it returned.
128-
129- Testing shows the leak:
130-
131- ``` python
132- # test_leaky.py
133- from leaky import Leaky
134-
135- def test_getter_leaks_internal_state () -> None :
136- leaky = Leaky([1 , 2 ])
137- leaky.numbers.append(999 ) # Changes the internal list
138- assert leaky.numbers == [1 , 2 , 999 ]
139- ```
140-
141126Mutating the returned list manipulates the internal state.
142127
143128## Plugging Leaks Is Tedious
0 commit comments