DEV Community

Deepak Singh
Deepak Singh

Posted on

OOP Didn’t Invent Anything New — It Just Gave Us Discipline

Deepak Singh

3 min read · 13 hours ago


Encapsulation, inheritance, polymorphism — we had them long before OOP.

What OOP really did was add discipline, structure, and accessibility.

And that’s exactly why it changed everything.


The Big Misconception

When people talk about Object-Oriented Programming (OOP), they often ask:

“But didn’t OOP give us encapsulation, inheritance, and polymorphism?”

The truth: No, it didn’t.

All three concepts existed before OOP.

What OOP brought was a way to enforce constraints and discipline around how we use them.

Surprisingly, that’s what made OOP revolutionary.

Let’s break it down.


Encapsulation

Encapsulation means hiding data and exposing behavior through controlled interfaces.

But hiding from whom? And why?

Encapsulation in C

Long before OOP, C programmers used header files (.h) and implementation files (.c) to achieve encapsulation.

// mathlib.h
#ifndef MATHLIB_H
#define MATHLIB_H

int add(int a, int b);
#endif
Enter fullscreen mode Exit fullscreen mode
// mathlib.c
#include "mathlib.h"

int add(int a, int b) {
    return a + b;
}
Enter fullscreen mode Exit fullscreen mode
// main.c
#include <stdio.h>
#include "mathlib.h"

int main() {
    printf("%d\n", add(3, 4)); // Output: 7
    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Here, the caller knows a function exists but not how it works.

The same applies to structs: we can declare them without exposing internals, forcing access through functions.

This abstraction might feel like “hiding a book from ourselves” — but it’s intentional.

By forcing ourselves to interact through controlled functions, we reduce coupling and make future changes safe.

What OOP Added

OOP gave us keywords like private, protected, and public.

class Account {
private:
    double balance; // hidden
public:
    void deposit(double amount) { balance += amount; }
    double getBalance() { return balance; }
};
Enter fullscreen mode Exit fullscreen mode

This made encapsulation easier to apply in a single file, even though compilers still know about structure layouts.

So, OOP didn’t invent encapsulation — it just made it mainstream and practical.


Inheritance

Inheritance means reusing code by deriving one type from another.

But guess what? Programmers were already doing it in C.

Inheritance in C

typedef struct {
    int x;
    int y;
} Point;

typedef struct {
    Point base;   // reuse Point
    char name[50];
} NamedPoint;
Enter fullscreen mode Exit fullscreen mode

By embedding one struct inside another, C developers could simulate inheritance.

But it only worked for single inheritance, and managing it got messy.

What OOP Added

class Point {
public:
    int x, y;
};

class NamedPoint : public Point {
public:
    std::string name;
};
Enter fullscreen mode Exit fullscreen mode

OOP gave us first-class syntax.

Clean, readable, and no casting tricks required.

So again, inheritance wasn’t new.

OOP just made it simple and expressive.


Polymorphism

Polymorphism means the same function name can behave differently depending on context.

In OOP

class Shape {
public:
    virtual void draw() = 0;
};

class Circle : public Shape {
public:
    void draw() override { std::cout << "Drawing Circle\n"; }
};
class Square : public Shape {
public:
    void draw() override { std::cout << "Drawing Square\n"; }
};
Enter fullscreen mode Exit fullscreen mode

Different objects (like Circle or Square) can implement the same function (e.g., draw) in different ways.

Polymorphism in C

Before OOP, C programmers used function pointers to achieve polymorphism.

#include <stdio.h>

typedef struct {
    void (*read)();
} Device;
void readFromConsole() { printf("Reading from console\n"); }
void readFromFile()    { printf("Reading from file\n"); }
int main() {
    Device console = { readFromConsole };
    Device file = { readFromFile };
    console.read(); // Reading from console
    file.read();    // Reading from file
}
Enter fullscreen mode Exit fullscreen mode

That worked, but it was clunky and risky.

OOP gave us a safer and cleaner way.


Why Polymorphism Changed Everything

Among the three pillars, polymorphism was the game-changer.

Imagine plugging a new device into your PC.

Without polymorphism, you’d need to rewrite functions for each new device.

With polymorphism, as long as the device implements the same interface, your existing code just works.

Even more importantly, polymorphism enables Dependency Inversion.

Higher-level code no longer depends on low-level details.

Instead, both depend on shared contracts (interfaces).

This makes systems:

  • More maintainable
  • Easier to extend
  • Loosely coupled

That’s real power.


Final Thoughts

OOP didn’t invent encapsulation, inheritance, or polymorphism.

Those ideas existed long before.

But OOP gave us discipline, structure, and accessibility — making these ideas practical for everyday programming.

And that’s the real lesson:

Building great software isn’t always about inventing something new.

Sometimes, it’s about applying the right constraints to create powerful systems.


References

Martin, R. C. (2017). Clean Architecture: A Craftsman’s Guide to Software Structure and Design. Prentice Hall.

Top comments (0)