Intro to OOP

Clock icon
Thu Oct 15 2026
Calendar icon
8 mins

In this article, we will find out more about the Object-Oriented Programming paradigm. But first, we need to understand what a programming paradigm is.

What is a programming paradigm?

A programming paradigm (or technique) defines how programs are decomposed. Basically, it dictates how you slice the problem you want to solve and what the smaller pieces look like.

The different programming paradigms are divided into two main categories:

More about OOP

Object-Oriented Programming (OOP) shifts the fundamental building block of software from algorithms and procedures to interacting objects. Rather than writing a chronological sequence of steps that transform passive initial data into a result, OOP organizes a program as a collection of cooperating objects that encapsulate both state (data) and behavior (methods).

History of OOP

OOP emerged because as software systems grew in size and complexity, procedural programming faced difficulties since data and the functions operating on them were not strictly bound together. The first OOP language was Simula, followed later by languages such as Smalltalk, C++, and Object Pascal. In the 1990s, the OOP paradigm began to be widely accepted and used, marking the appearance of another fundamental language: Java.

Criteria of OOP

A program uses OOP when it meets the following criteria:

  1. It is organized as a collection of cooperating objects.
  2. Each object represents an instance of a class (classes are user-defined abstract data types).
  3. Classes are organized into a class hierarchy linked via inheritance relationships.

The object model

The object model is a conceptual framework that organizes complex software systems into a network of autonomous, cooperating entities called objects, rather than a flat list of instructions operating on passive data.

What is OOP?

Object-Oriented Programming is a paradigm in which programs are organized as a collection of cooperating objects. It uses objects rather than algorithms as its fundamental building blocks.

Each object is an instance of a class, and the classes themselves are linked through inheritance, forming a hierarchy. Basically, a class represents a blueprint that consumes no data memory on its own, defining what data an entity holds and what operations it can perform.

Diagram about the relationship between a class and an object

The object model relies on 4 major principles:

  1. Abstraction
  2. Encapsulation
  3. Modularity
  4. Hierarchy

Abstraction

Abstraction involves ignoring non-essential implementation details in order to focus on what is essential. It requires identifying similarities among different entities and focusing on their shared aspects, while also highlighting what makes an object distinct from others.

It operates at the design and conceptual level, answering the question: “What does this object represent and what can it do?”

It is implemented in code via:


Encapsulation

Encapsulation enforces information hiding, meaning that objects cannot directly alter the internal state of other objects. Instead, these operations can only be performed through the object’s own methods, which make up its interface.

It ensures that structure is separated from behavior—structure is hidden inside the internal implementation, while behavior is exposed through the public interface.

To respect encapsulation, member data variables are generally declared with the private or protected keywords, restricting direct external access and making them accessible only through the class’s own member functions.

Based on the operation they perform on the manipulated data, these methods are called getters (if they read the data) or setters (if they modify it).

Getter and setter functions provide major advantages such as:

Abstraction vs. Encapsulation


Modularity

Modularization is the process of partitioning a program into individual components called modules. It reduces complexity by establishing well-defined boundaries within the program.

It is implemented by grouping related classes and interfaces into units such as packages or modules. This allows separate compilation and makes teamwork easier (each team can work independently on different packages).

Two principles lie at the foundation of modularity:


Hierarchy

Hierarchization is the method of ordering abstractions into structured levels. There are two primary types of hierarchies:

These two types are commonly known as “IS-A” vs. “HAS-A” hierarchies. The differences can be seen in the following table:

Feature Type hierarchy (IS-A) Aggregation hierarchy (HAS-A)
Mechanism Inheritance (extends in Java) Object composition (a complex object is built from simpler objects)
Example A dog is an animal A dog has 4 legs
Binding time Static (compile time) Dynamic (components can be swapped at runtime)

Inheritance

Inheritance enables the construction of new classes (called derived classes or subclasses) that retain the characteristics and behavior (member data and functions) of a previously defined class (called a base class or superclass).

Core advantages include:

Java only allows single class inheritance, meaning that a derived class can only have one direct base class. It is declared using the extends keyword.

Example of inheritance relationships

The protected keyword

In Java, if we define a member in a base class using the private keyword, no derived class can directly access that private member. If we want to allow subclasses (and classes within the same package) to access parent members while still restricting external classes, we use the protected keyword instead.

The super keyword

In Java, to refer to the immediate parent class, we use the super keyword. Furthermore, to invoke the parent’s constructor, we call super().


Other OOP principles

Function overloading

Function overloading means that a function executes different operations depending on the context in which it is used (for example, the + operator in Java performs addition for numbers, but concatenation for strings).

Practically, multiple functions can share the exact same name within the same scope, provided they can be differentiated by the number or data types of their arguments. For example, int abs(int) and double abs(double) are differentiated by their parameter type (abs(1) calls the int version, while abs(1.0) calls the double version).

Important: Functions cannot be overloaded based solely on their return types.

Polymorphism

In its strict sense, polymorphism is the property of a function that can execute the exact same effect on values of different data types. An example is the & operator in C, which extracts the memory address from an int, double, char, or struct variable alike.

In broader OOP practice, polymorphism is treated as a core pillar divided into two categories:

Method overriding

Method overriding provides the ability to redefine inherited methods specifically for derived (child) classes. Unlike overloading, an overridden method must have the exact same name, parameter types, and return type (or a covariant return type).

It strictly requires inheritance, and in Java, overriding should be signaled using the @Override annotation above the child method. A subclass can also invoke the parent’s original overridden method using the super.methodName() syntax.