What are Abstract Data Types

An Abstract Data Type (ADT) is a conceptual model that specifies the behavior of an element independently of its implementation. Rather than describing how something is implemented, it describes, from the perspective of the consumer, what operations are available and the semantics those operations must satisfy. Although often introduced using familiar data structures such as stacks and queues, the same principles apply equally well to larger software abstractions.

Historically, ADTs emerged from work on formal specification and specification of data abstraction, where precise behavioral descriptions were used both to reason about correctness and to guide implementations that were correct by construction. These efforts were presented by Barbara Liskov and Stephen Zilles in their 1975 publication Specification Techniques for Data Abstractions.

An ADT typically defines a domain, the operations that may be performed on that domain, and the invariants those operations must preserve. An ADT is not itself a programming language type. It is a specification that may be realized by one or more concrete types.

An ADT defines the externally observable behavior of an abstraction, allowing consumers to reason about what it does without needing to understand how it is implemented.

Throughout this series, I will view an ADT through three related elements:

These elements do not replace the classical definition of an Abstract Data Type. Instead, they provide an architectural extension that offers a repeatable way to reason about and design software abstractions.

Many object-oriented principles—encapsulation, modularity, separation of concerns—align naturally with Abstract Data Types because both emphasize abstraction over representation. However, an ADT is not tied to object-oriented programming - the concept of data abstraction predates OO and influenced much of the OO thinking . An ADT can be implemented equally well in C, Swift, Rust, or even hardware. Unlike interfaces or abstract classes, which primarily define an operational surface, this architectural lens explicitly considers the abstraction’s state together with the constraints that govern its correct behavior.

Referring back to Specification Techniques for Data Abstractions, Liskov and Zilles identify one goal of formal specifications as supporting “programming methodologies leading to programs which are correct by construction.” That phrase captures the motivation for the remainder of this series. By treating Abstract Data Types as architectural design specifications rather than simply implementation artifacts, we define the expected behavior of a component independently of its construction. Those specifications provide a foundation for implementation, verification, and—where supported by the language—type systems that can eliminate certain classes of errors before runtime.

This article is the beginning. Understanding what an Abstract Data Type is provides the foundation, but it does not tell us how to design one. In the next article, we’ll build upon this architectural lens to develop a repeatable methodology for specifying and designing Abstract Data Types.