Encapsulation bundles data with the operations that manage it, so callers do not directly edit internal state. Instead of keeping an array’s size in a shared variable, an array object stores and updates its own size. section 2.10
A class provides the boundary: methods validate and change the data, while internal attributes hold details such as capacity and current size. This prevents callers from accidentally desynchronizing related values. section 2.10
Encapsulation becomes especially valuable when a data structure must preserve an invariant:
- An unsorted array keeps its size with the instance and updates it through array operations. section 2.10
- A sorted array restricts changes to insert and delete methods, protecting the requirement that entries remain sorted. section 3.3
- Composition places a core array inside the higher-level class, rather than inheriting from it; this offers more design flexibility. section 2.10
An encapsulated array
UnsortedArray stores the underlying array, maximum capacity, and current size as instance attributes. Clients use the class operations instead of maintaining the size separately. section 2.10
class UnsortedArray:
def __init__(self, max_size, typecode = 'l'):
self._array = Array(max_size, typecode)
self._max_size = max_size
self._size = 0
The constructor shows encapsulation through bundled state and composition: the wrapper owns its size while delegating storage to an internal Array. section 2.10













