Search Knowledge

© 2026 LIBREUNI PROJECT

Programming Concepts & Paradigms / Computational Paradigms

Object-Oriented Foundations: Objects, Classes, and Messages

Object-Oriented Foundations: Objects, Classes, and Messages

Object-Oriented Programming (OOP) addresses the challenge of state management by integrating data and behavior into single, modular units called objects. In procedural systems, data and the logic that manipulates it are separate, which complicates tracking state changes as software systems expand. OOP provides a conceptual framework for managing this complexity through abstraction, classification, and controlled communication.

1. The Four Pillars of OOP

Four fundamental principles serve as the foundation for managing complexity and ensuring reuse within object-oriented systems.

I. Encapsulation (Data Hiding)

Encapsulation involves concealing the internal state of an object and exposing only a defined, public interface.

  • Purpose: To prevent external components from inadvertently corrupting an object’s internal state.
  • Mechanism: The use of access modifiers (private, protected, public) ensures that internal data (fields) can only be accessed or modified via public methods (getters/setters). This creates a “contract” that the object’s implementation remains valid regardless of external interaction.

II. Abstraction (Simplification)

Abstraction focuses on revealing only essential functionality while hiding the intricate implementation details.

  • Example: A Database object provides a simple save() method. The user does not need to understand socket protocols, authentication handshakes, or file system writing mechanisms to utilize the storage capability. Abstraction allows programmers to reason about high-level behavior rather than low-level mechanics.

III. Inheritance (Code Reuse)

Inheritance enables a subclass to derive properties and methods from a superclass.

  • Relationship: It represents an “is-a” relationship (e.g., a Dog is-a Animal). This facilitates the hierarchy of logic, allowing for code reuse and the reduction of logical duplication across related entities.

IV. Polymorphism (Many Forms)

Polymorphism permits objects of distinct types to be treated as instances of a common base type.

  • Example: A list of Shape objects may contain Circle, Square, and Triangle instances. Invoking draw() on each object triggers specialized behavior tailored to the specific subtype (late binding). This allows systems to be extensible without modifying existing code that operates on the base type.

2. The Philosophical Divide: Alan Kay vs. Simula

Object-Oriented Programming originated from two distinct philosophies with vastly different priorities.

The Messaging Model (Alan Kay & Smalltalk)

Alan Kay, who coined the term “Object-Oriented,” viewed objects as autonomous cells. In this model, the primary focus is on Messaging rather than classification.

  • Operations are viewed as “sending a message” to an object.
  • The receiving object then decides how to respond to that message at runtime. This leads to a highly dynamic system where objects can change their behavior or even delegate messages they don’t understand to other objects.

The Class Model (Simula & C++)

The tradition derived from Simula 67 emphasizes classification and structure.

  • Objects are treated as “instances” of static blueprints called Classes.
  • Relationships and method dispatch are often fixed at compile-time (early binding), prioritizing type safety, memory efficiency, and predictable performance. This is the model most familiar to Java and C++ developers.
Please use CSS style instead of skinparam paddingThe OOP DivideSmalltalk MessagingC plus plus and JavaClassificationLate BindingDynamic NatureObjects all the way downEarly BindingStatic Type SafetyClasses as Blueprints

3. Composition over Inheritance

Over-reliance on inheritance can lead to rigid, deeply nested hierarchies that are difficult to modify. This results in the Fragile Base Class Problem: an seemingly innocuous alteration to a superclass can inadvertently disrupt several levels of subclasses that depend on the internal behavior of the parent.

Modern engineering emphasizes Composition over Inheritance (the “HAS-A” relationship).

  • Inheritance: “A Dog is an Animal.” (Tightly coupled)
  • Composition: “A Dog has a Heart.” (Loosely coupled)

By building complex behavior through the combination of smaller, specialized objects (delegation), developers create systems that are much more flexible and resilient to change.

4. Classes vs. Prototypes

Object-orientation is not exclusively class-based.

  • Class-Based (Java, C#): Requires a predefined blueprint (class) before an object can exist. Classification is static and central to the language design.
  • Prototype-Based (JavaScript, Self): Objects are derived through the cloning and modification of existing objects. If an object needs a new method, it is added directly to that instance or its prototype link.

5. The SOLID Principles

To guide robust object-oriented design, engineers follow the SOLID principles:

  1. Single Responsibility: A class should possess only one reason for change, focusing on a single concern.
  2. Open/Closed: Software entities should be open for extension (adding new subtypes) but closed for modification (not changing existing code).
  3. Liskov Substitution: Subtypes must be perfectly interchangeable with their base types without altering program correctness.
  4. Interface Segregation: Clients should not be forced to depend on broad, general interfaces with methods they do not utilize.
  5. Dependency Inversion: High-level modules should depend on abstractions (interfaces), not on concrete implementations, reducing coupling between components.

6. Interactive Exercise: Identifying the Pillar

Identify the OOP principle demonstrated in the implementation of the BankAccount class.

public class BankAccount {
    private double balance; // Internal State
    
    public void deposit(double amount) {
        if (amount > 0) balance += amount;
    }
}

Identifying the Pillar

class BankAccount {
  private double balance; 

  public void deposit(double amount) {
    if (amount > 0) {
      this.balance += amount;
    }
  }

  // This design demonstrates:
  String pillar = "";
}

7. Summary

Object-oriented programming remains a standard for large-scale application development. By integrating data and behavior, it provides tools for modeling complex domains through abstraction and controlled interfaces. However, the paradigm’s reliance on state mutation poses challenges for concurrent and distributed systems, leading developers to integrate functional programming concepts into modern OO languages.