Abstract data type 2026-10-13
An abstract data type specifies values and operations independently of their storage. A FIFO queue has ordered sequences as its abstract values; an array and a linked list can represent those same values. A representation invariant identifies valid storage states, and an abstraction function says what each valid state means.[ref]
Reading 13: Abstraction Functions & Rep Invariants. Reading 13, Rep Invariant and Abstraction Function: representation values, abstract values, AF and RI
Abstraction function 2026-10-13
An abstraction function maps a valid concrete representation to its abstract value. Write and . Different storage states can denote the same abstract value. Correct implementation requires both preservation of the representation invariant and agreement with the specified operation after applying the abstraction function; preserving a length bound alone would not prove first-in, first-out behavior.
Bounded queue with encapsulation 2026-10-13
Consider an original FIFO queue example storing immutable labels, with fixed positive integer capacity . Its abstract state is a finite sequence , with . The API has
enqueue(x), dequeue(), peek() and size(). Successful enqueue returns ok; a full queue returns full and is unchanged. Successful dequeue returns the first label and removes it; an empty queue returns empty and is unchanged. peek returns the first label or empty without modification, and size returns . The status results are distinct from stored labels.For a compact array representation , fix and require the representation invariantThe abstraction function is . Only these first entries matter; unused slots have no abstract meaning. On successful
enqueue(x), write and then set . On successful dequeue(), save , shift the remaining entries left, and decrement . Testing the full or empty case before updating gives the specified unchanged failure state.Permitted queue calls preserve valid states; an unrestricted count write bypasses the API
. Details. With and ,
enqueue(C) produces ; enqueue(D) returns full without change. A raw write violates the representation invariant. More subtly, changing the count from two to one satisfies its bounds but discards without a permitted operation. Validity of the storage state and legality of the API transition are different obligations. A setter for every storage field would surrender the useful boundary even if its name looked like an ordinary operation. Encapsulation (computer programming) 2026-10-13
Encapsulation bundles related program state and operations or hides implementation details behind an interface. Encapsulation in object-oriented programming realizes this through objects and their permitted operations; encapsulation also applies to modules outside object-oriented programs.
The useful boundary is a promise: clients request operations through an API, and the implementation maintains a representation invariant. Instead of proving that every client updates several storage fields consistently, prove that the permitted operations preserve the representation invariant. Information hiding also leaves room to replace the data structure while keeping the client-facing behavior, a property called representation independence.
Bundling state and operations alone does not establish that promise. Representation exposure can let clients bypass the API. A
private annotation alone is not a security guarantee: it does not establish correctness of operations, isolation from hostile code or safe handling of shared mutable storage. The examples below concern sequential calls with no concurrent access and no client access to internal storage; they do not claim protection against arbitrary memory modification. Representation exposure 2026-10-13
Representation exposure gives outside code access that can modify storage on which the representation invariant or promised behavior depends. Returning the internal array exposes a route around the API; merely hiding the field name does not close it. Incoming shared mutable storage can create the same problem. Copies or immutable values can prevent such modification, but their costs and sharing rules belong in the design.[ref]
Reading 13: Abstraction Functions & Rep Invariants. Reading 13, Invariants, Immutability: mutable aliases through both returned values and constructor arguments
The bounded queue with encapsulation deliberately stores immutable labels. A FIFO queue of mutable objects needs a separate promise about whether changing a returned object changes stored content; protecting the queue's ordering and size does not automatically make every stored object immutable.
Representation independence 2026-10-13
Representation independence means that clients restricted to the promised API cannot distinguish implementations by the specified results and state transitions. State what observations count: equal returned labels and failure statuses do not imply equal running times, allocations or physical layouts. If the API also promises a resource bound, a replacement must meet that bound too.
Replace the compact array in the bounded queue with encapsulation by a circular buffer with storage , front index and count . Its representation invariant is , , and . Its abstraction function reads the occupied slots using modular arithmetic:On successful
enqueue(x), write and increment . On successful dequeue(), return , replace by and decrement . Full and empty failures do not alter storage. peek and size have the same abstract meanings as before. Keeping a count distinguishes a full circular buffer from an empty one even when both would have the same next insertion index.For , start empty, enqueue , dequeue twice, enqueue , try to enqueue , then
peek and size. Both implementations return from the removals, report full for , and finish with front , size three and abstract sequence . The compact array stores from index zero; the circular buffer stores with . Their abstraction functions explain why different stored entries describe the same ordered content.Under constant-cost slot access and index arithmetic, with no resizing and labels that fit in one slot, the compact array does slot moves on a successful removal: worst-case time complexity as capacity varies. The circular buffer does no slot moves and uses worst-case time complexity for all four operations. Both allocate slots initially; that construction cost is separate. These are operation-count claims in Big O notation, not measured timings. The short correctness outline checks that each implementation's abstraction function produces the specified new sequence and return value after every successful or rejected call. Repeating that check gives equal traces for clients using only this API.
Representation invariant 2026-10-13
A representation invariant specifies which concrete storage states are valid at the API boundary. Construction must establish it, and each completed operation must preserve it. Internal steps may temporarily violate it only while that state is inaccessible to observers; callbacks or concurrent access would require further reasoning.[ref]
Reading 13: Abstraction Functions & Rep Invariants. Reading 13, How to Establish Invariants: creation, preservation and absence of representation exposure
The short proof pattern is mathematical induction on the number of completed calls: the initial state satisfies ; every permitted transition from an -state ends in an -state; hence every state observable through the API satisfies . An unrestricted external write falls outside this argument.

