Object-Oriented Programming
· Last updated: 2026-06-30 · 20 min read
People often call design patterns a universal solution. Now that OOP has been established and the Gang of Four's book on design patterns has taken on the status of a kind of gospel, many developers open the pattern book, look only at the structural diagrams, and write their code from there. The result is often a rigid implementation with no flexibility.
In learning design methodologies and patterns, we constantly waver in the gap between 'schematic understanding' and 'practical experience'. As Christopher Alexander noted, to decompose a design method away from the substance of design is ultimately to speak of nothing but an empty abstraction.1
There are actually many threads to explore before getting to patterns, including idioms, but that discussion is reserved for the Programming Idioms article. This piece focuses on the identity of OOP as it surrounds the topic of patterns.
Object-Oriented Programming (OOP) is a programming paradigm that organizes a program by bundling data and the procedures that manipulate that data into units called objects. Its core idea is encapsulating, into a single unit, the data and functions that procedural programming kept separate. The paradigm originated in the Simula language in the 1960s and has since become one of the most widely used paradigms in the software industry.
An important caveat: the OOP we commonly use today cannot be reduced to the message-based object orientation that Alan Kay originally envisioned. It is the result of a mixture: the class and inheritance model of Simula 67, the 1970s research into CLU2, Alphard, abstract data types, and access control, Smalltalk's message passing, and the industry-standard class-based OOP that emerged through Bjarne Stroustrup, Peter Wegner, Bertrand Meyer, Grady Booch, and others. The conceptual origins span the 1960s through the 1970s, while standardization within the industry proceeded strongly in the late 1980s through the early 1990s. The OOP encountered in textbooks, interviews, and design pattern books is a later, simplified form of this long evolution.
For other meanings, see the following:
Alan Kay's original conception of object orientation: message-based object orientation
Prototype-based object orientation: prototype-based programming
The definition of OOP varies subtly depending on the era and the person defining it. No single authoritative definition exists; multiple definitions coexist.
Alan Kay (1967; retrospectively clarified in 2003) : Views messaging, local retention and hiding of state and process, and extreme late binding as the core principles.
Grady Booch (1991): Proposes the Booch Object Model, composed of 4 major elements (Abstraction, Encapsulation, Modularity, Hierarchy) plus 3 minor elements (Typing, Concurrency, Persistence).
Bertrand Meyer (1988, OOSC): A formal OOP definition centered on Design by Contract.
Peter Wegner (1987, OOPSLA): Distinguishes progressively among object-based, class-based, and object-oriented.
Later mainstream industry definition: A simplification of the above traditions into three pillars of Encapsulation, Inheritance, and Polymorphism (with no single clearly identifiable author as its source).
The gap among these definitions is not merely an academic debate; it serves as the starting point for deciding how OOP is applied in practice.
Simula I was a precursor language designed for discrete-event simulation, while the language recognized today as the direct ancestor of object-oriented languages is Simula 673. Developed by Norwegian researchers Kristen Nygaard and Ole-Johan Dahl, Simula 67 combined classes, objects, inheritance, late binding, and dynamic object creation, and it became the origin of all subsequent class-based OOP.4
Alan Kay is widely credited as the person who verbally coined the term "object-oriented programming." 5However, this does not mean he was the first to use it in print. Kay's retrospective accounts of using this phrase in the late 1960s are significant, but the documented history of "object-oriented" appearing in publications is more complex. Kay later realized his vision through Smalltalk at Xerox PARC.
In a 2003 email to Stefan Ram, Kay explicitly stated that what he had meant by object-oriented programming consisted of the following three things.5
Messaging
Local retention and protection and hiding of state-process
Extreme late-binding of all things
To put it plainly, the object Kay had in mind was something like a small computer. Each object exists independently, and the structure is one where objects collaborate by passing messages to one another. Rather than designing class hierarchies, the central question was "what messages flow between objects."
But framed this way, this is not quite the OOP concept most of us picture. So where did the concept we commonly talk about actually come from?
In 1976, MIT Computation Structures Group Memo 137 by Anita K. Jones and Barbara Liskov, titled "An Access Control Facility for Programming Languages," grouped Simula 67, CLU, and Alphard together under the label "object-oriented languages."6 In this context, object-oriented referred less to Smalltalk-style messaging philosophy and more to abstract data types, hiding of object representations, typed operations, and access control.
Why does this matter? Because the history of OOP cannot be told through the Alan Kay/Smalltalk lineage alone. The class-and-object tradition that began with Simula developed along a separate theoretical trajectory, passing through CLU, Alphard, abstract data type research, and access control studies. The class-based OOP we see today in Java, C#, and C++ is best understood as the industrial synthesis of that tradition with the Smalltalk tradition.
Personal note: Rochus Keller helped me trace this historical thread. His site is linked below.
rochus-keller.ch
Rochus Keller's Website | About me and what I do
The OOP we use today was not defined by any single person; it took shape gradually through the collaborative contributions of many individuals from the late 1980s through the early 1990s.
Bjarne Stroustrup released C++, which transplanted Simula's class model into the C language.7 C++ was the first decisive language to bring class-based OOP into mainstream industry, and it effectively became the reference point for every major OOP language that followed.
In his OOPSLA 1987 paper "Dimensions of Object-Based Language Design," Peter Wegner proposed the following graduated distinction.8
Object-based: objects + Encapsulation (e.g., Ada, Modula-2)
Class-based: object-based + Classes (e.g., CLU)
Object-oriented: class-based + Inheritance (e.g., Smalltalk, C++)
This classification would go on to directly influence the formation of the popular three pillars of OOP.
Bertrand Meyer published Object-Oriented Software Construction (OOSC, 1988).9 Drawing on his own Eiffel language, he established the formal foundations of OOP, including Design by Contract, invariants, and class invariants. Meyer's OOSC and Booch's OOAD stood as the two pillars of OOP education throughout the 1990s.
Grady Booch published Object-Oriented Analysis and Design with Applications (1991).10 In this book, Booch defined OOP as follows (p.37):
"Object-oriented programming is a method of implementation in which programs are organized as cooperative collections of objects, each of which represents an instance of some class, and whose classes are all members of a hierarchy of classes united via inheritance relationships."
This definition can be summarized in three propositions:
OOP uses objects, not algorithms, as its fundamental logical building blocks.
Each object is an instance of some class.
Classes are linked to one another through inheritance relationships.
That said, Booch's real contribution lies less in the definition above and more in his object model (4 major + 3 minor elements) and his visual notation (Booch notation). For details, see the Booch's Object Model: 4 major + 3 minor section.
Against the backdrop of class-based OOP taking hold through the 1980s and 1990s, one towering programming classic appeared in 1994: the GoF Design Patterns. Its four authors, Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, gave rise to the nickname Gang of Four.
The GoF drew inspiration from Christopher Alexander's A Pattern Language (1977), yet ironically fell into the very trap Alexander had warned against: the schematization of methodology. The moment patterns were reduced from a question of "why" to a question of "what," a culture of memorizing diagrams and forcing them into code took hold. For details, see the document on the schematization trap of patterns.
Java (1995) and, later, C# (2002) essentially mandated class-based OOP at the language level. Java's design, which required all code to reside inside a class, solidified class-based OOP as the standard paradigm in enterprise software.
The rise of functional programming and the emergence of data-oriented design brought OOP's limitations into serious discussion. It was also during this period that Alan Kay himself began distancing class-based OOP from his original intent.
Chapter 2, "The Object Model," in Booch's 1991 book explicitly identifies the elements of the object model as follows.1011
Category | Element | Description |
|---|---|---|
Major (required) | Abstraction | Extracting essential characteristics |
Major (required) | Encapsulation | Hiding the internals of an abstraction |
Major (required) | Modularity | Decomposing into units of high cohesion and low coupling |
Major (Required) | Hierarchy | The hierarchy of "is-a" and "part-of" relationships |
Minor (Optional) | Typing | Type safety grounded in abstract data types |
Minor (Optional) | Concurrency | The distinction between active and passive objects |
Minor (Optional) | Persistence | Preserving object state across time and space |
Major (required)
Abstraction
Extracting essential characteristics
Major (required)
Encapsulation
Hiding the internals of an abstraction
Major (required)
Modularity
Decomposing into units of high cohesion and low coupling
Major (Required)
Hierarchy
The hierarchy of "is-a" and "part-of" relationships
Minor (Optional)
Typing
Type safety grounded in abstract data types
Minor (Optional)
Concurrency
The distinction between active and passive objects
Minor (Optional)
Persistence
Preserving object state across time and space
There are a few notable points here.
Booch did not specify "Polymorphism" as a standalone element of the object model. Polymorphism is only implied within Hierarchy.
Booch does not treat "Inheritance" as an independent element; instead, he subsumes it as one form of Hierarchy. Hierarchy is a broader concept that encompasses not only the "is-a" relationship corresponding to inheritance, but also the "part-of" relationship associated with aggregation and composition.
Booch's model is richer than the popular three-pillars framework in that software engineering concepts such as Modularity, Concurrency, and Persistence are explicitly incorporated into the object model.
There is therefore a considerable gap between Booch's actual model and the "three elements" we encounter in bootcamps or job interviews.
The Encapsulation, Inheritance, and Polymorphism commonly cited as the three elements (or three pillars) of OOP are not a definition established by any single author, but a popular formulation that gradually solidified within the industry.
Simula 67 (1967): Introduced classes, instances, and inheritance at the language level.
Smalltalk (1972~): Implemented encapsulation and polymorphism through message passing.
1970s CLU, Alphard, and the abstract data type lineage: Anita K. Jones and Barbara Liskov referred to Simula 67, CLU, and Alphard as "object-oriented languages" in 1976.6 In this context, the central concerns were abstract data types, representation hiding, type operations, and access control, rather than class hierarchies.
Peter Wegner (1987): Proposed a graduated distinction among "object-based," "class-based," and "object-oriented" languages, and clearly identified inheritance as the defining characteristic that sets object-oriented programming apart from other paradigms.8
The C++ camp (1985 through the 1990s): Industrial training materials began to circulate the formulation that "a true OOP language is one that possesses all three of encapsulation, inheritance, and polymorphism." Statements like the following became common.
Using encapsulation alone (that is, defining and using classes without employing inheritance or polymorphism) is commonly called object-based programming. To practice true OOP, all three pillars (encapsulation, inheritance, and polymorphism) must be used.12
The Java (1995~) textbook era: This formulation became entrenched in standard educational materials.
The "three elements" are not Booch's invention. Booch's book presents a model of four major elements plus three minor ones, nothing more.
The "three elements" are not Kay's definition either. Kay's definition centers on messaging, encapsulation, and dynamic binding.
The "three elements" are an industry-consensus vernacular formulation that cannot be traced back to any single book.
Failing to recognize this leads to the error of reducing the history of OOP to one person's book (Booch's).
Personal note: In fact, the more common view of OOP history tends to attribute it primarily to Alan Kay's work alone, so the misconception that it was Booch's story may have been entirely my own perspective.
OOP has effectively branched into two distinct streams.
Distinction | Message-Based OOP | Class-Based OOP |
|---|---|---|
Origin | Smalltalk (1972) | Simula 67 (1967) |
Unit | Small computers exchanging messages | Instances of a class |
Core Idea | Messaging, Dynamic Binding | Classes, Inheritance, Composition |
Coupling | Extreme late binding | Compile-time type resolution (generally) |
Key Figures | Alan Kay | Kristen Nygaard, Bjarne Stroustrup, Bertrand Meyer, Grady Booch |
Representative Languages | Smalltalk, Self, Objective-C | C++, Java, C#, Eiffel |
Intellectual Descendants | Actor Model, the messaging aspect of ECS, Erlang/Akka-style message-based concurrency models | Enterprise OOP, GoF Design Patterns |
Origin
Smalltalk (1972)
Simula 67 (1967)
Unit
Small computers exchanging messages
Instances of a class
Core Idea
Messaging, Dynamic Binding
Classes, Inheritance, Composition
Coupling
Extreme late binding
Compile-time type resolution (generally)
Key Figures
Alan Kay
Kristen Nygaard, Bjarne Stroustrup, Bertrand Meyer, Grady Booch
Representative Languages
Smalltalk, Self, Objective-C
C++, Java, C#, Eiffel
Intellectual Descendants
Actor Model, the messaging aspect of ECS, Erlang/Akka-style message-based concurrency models
Enterprise OOP, GoF Design Patterns
Key Point: The two branches represent a divergence of paradigms, not a personal rivalry. Kay and Booch were solving different problems. Kay envisioned loose-coupling systems for the future of personal computing embodied in the Dynabook, while Booch sought to establish analysis and design methodologies for complex systems (such as Ada-based military software). Both used the same term, "OOP," yet they were building fundamentally different species of paradigm.
All concepts in this section are described with reference to class-based OOP.
Class: a blueprint for creating objects. It defines data fields and methods.
Object: an instance of a class. A unit materialized in memory.
Message: the means of interaction between objects. In class-based OOP, this is typically implemented as a method call, though Kay's original intent was a looser form of coupling.
A mechanism that groups related data and methods into a single unit and hides the internal implementation from the outside world.
public class BankAccount
{
private decimal balance;
public void Deposit(decimal amount)
{
if (amount <= 0) return;
balance += amount;
}
public decimal GetBalance() => balance;
}
For more details, see the Encapsulation article.
A mechanism by which one class inherits the properties and methods of another. It is used as a means of code reuse, though in modern practice Composition is often recommended instead.
A warning against overusing inheritance: "Composition over Inheritance" is a principle emphasized in the GoF Design Patterns book.13 Side effects of inheritance overuse include the diamond problem and violations of the Liskov Substitution Principle (LSP).
An approach in which an object contains other objects as fields and delegates the required behavior to those objects to compose functionality. Where inheritance expresses an "is-a" relationship, Composition generally expresses a "has-a" or "part-of" relationship.
Composition makes reuse and extension possible without deepening class hierarchies, and offers the advantage of allowing composed objects to be swapped out at runtime. That said, as delegation relationships among objects multiply, the execution flow can become scattered and harder to follow.
public interface IDiscountPolicy
{
decimal Discount(decimal price);
}
public class Order
{
private readonly IDiscountPolicy discountPolicy;
public Order(IDiscountPolicy discountPolicy)
{
this.discountPolicy = discountPolicy;
}
public decimal FinalPrice(decimal price)
{
return price - discountPolicy.Discount(price);
}
}
Key point: Inheritance is reuse by inheriting a parent class's implementation, while Composition is reuse by assembling and delegating to other objects. The GoF's "favor Composition over inheritance" does not mean inheritance should be prohibited; it means inheritance should not be abused solely for the sake of reusing implementations.
The ability to invoke different implementations through the same interface. It is classified as follows.
Subtype polymorphism: inheritance/interface-based
Ad-hoc polymorphism: method overloading
Parametric polymorphism: generics/templates
The act of extracting and representing only the essential characteristics of a complex system. Abstract classes and interfaces are the primary tools for this.
The five OOP design principles formulated by Robert Martin.14
Abbreviation | Principle | Description |
|---|---|---|
S | Single Responsibility Principle (SRP) | A class should have only one reason to change |
O | Open/Closed Principle (OCP) | Open for extension, closed for modification |
L | Liskov Substitution Principle (LSP) | Subtypes must be substitutable for their parent types |
I | Interface Segregation Principle (ISP) | Clients should not be forced to depend on interfaces they do not use |
D | Dependency Inversion Principle (DIP) | Depend on abstractions, not on concretions |
S
Single Responsibility Principle (SRP)
A class should have only one reason to change
O
Open/Closed Principle (OCP)
Open for extension, closed for modification
L
Liskov Substitution Principle (LSP)
Subtypes must be substitutable for their parent types
I
Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they do not use
D
Dependency Inversion Principle (DIP)
Depend on abstractions, not on concretions
GRASP (General Responsibility Assignment Software Patterns)
DRY Principle (Don't Repeat Yourself)
KISS Principle (Keep It Simple, Stupid)
YAGNI (You Aren't Gonna Need It)
Law of Demeter
Design by Contract — Bertrand Meyer
Formalized solutions to recurring design problems in OOP. The GoF's Design Patterns (1994) serves as the starting point. It is worth noting that these patterns are a direct product of class-based OOP.
Categories | Representative Patterns |
|---|---|
Creational | Singleton, Factory Method, Abstract Factory, Builder, Prototype |
Structural | Adapter, Decorator, Proxy, Facade, Bridge, Composite |
Behavioral | Strategy, Observer, Command, State, Visitor, Chain of Responsibility |
Creational
Singleton, Factory Method, Abstract Factory, Builder, Prototype
Structural
Adapter, Decorator, Proxy, Facade, Bridge, Composite
Behavioral
Strategy, Observer, Command, State, Visitor, Chain of Responsibility
For a detailed taxonomy, see the Design Patterns Index.
Note that in Kay/Smalltalk-style message-oriented OOP, some GoF patterns are absorbed into language features or dynamic message dispatch, allowing them to be expressed more concisely or in forms that differ from class-based C++/Java implementations.15
Intuitive for modeling the real world.
Promotes code reuse.
Improves maintainability when designed appropriately.
Well-suited for large-team development.
Enables use of a rich library of design patterns.
Increased complexity from over-abstraction
Object creation overhead (memory fragmentation, GC pressure)
Reduced data locality (cf. data-oriented design)
Method call overhead (virtual function table)
Shared mutable state problems in concurrent programming
As noted at the outset, the most fundamental criticism is that the moment a pattern is reduced to a diagram, it becomes the "empty illusion" that Alexander warned against. The practice of looking only at GoF diagrams and forcing them into code is called the pattern-matching anti-pattern.
Joe Armstrong (creator of Erlang) criticized OOP by saying, "The problem with object-oriented languages is they've got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."16
Personal note: In the end, you usually realize you needed the whole jungle after all. That's what makes programming so hard.
The functional programming camp views mutable state and side effects as fundamental flaws of OOP. Their argument is that reasoning becomes difficult because referential transparency is not guaranteed.
Mike Acton argued in his CppCon 2014 talk that OOP forces data layouts that cause cache misses.17 The AoS vs. SoA debate is the canonical example. In game development and high-performance computing, alternatives such as Entity Component System have risen to prominence.
Personal note: The problem is that data-oriented design (DOP) produces layouts that cause cognitive misses. Having to dig through all the code every time you want to see the full state of an entity is not a particularly pleasant experience.
Alan Kay, who is widely credited with coining the term OOP, later distanced his original vision from modern class-based OOP, arguing that it differs from the message-passing-centric model he originally intended.5 The OOP Kay originally envisioned places such emphasis on message passing and loose coupling that it is frequently compared to the Actor model.
Design Patterns
Design Patterns (Gang of Four)
Christopher Alexander
Pattern Language
Booch Object Model
Design by Contract
Wegner Classification
Procedural Programming
Data-Oriented Design
Entity Component System
Actor Model
Prototype-Based Programming
Multi-Paradigm Language
Domain-Driven Design
Categories: Programming Paradigms | Software Engineering | Computer Science | Pattern Index | Educational Resources