02/11/2026 09:58am

What Is OOP? Object-Oriented Programming Principles Explained
#Object-Oriented Programming
#What is OOP
#OOP principles
#Class vs Object
#Encapsulation OOP
#Polymorphism OOP
#OOP Python
Ask two developers whether OOP still matters and there is a good chance you will get opposite answers. One camp says OOP is the foundation every developer has to master, because popular languages like Java, C# and Python all put classes front and centre. The other camp says OOP is going out of date and plain functions are all you need. Both of these are claims, not settled facts, and beginners who hear both at once are often left unsure where to start.
In short: OOP (Object-Oriented Programming) is a way of writing programs that bundles related data and behaviour together into units called objects, with a class acting as a template for objects.
Today, Superdev Academy walks through how a class differs from an object, what the 4 principles of OOP look like in real code, what OOP is good at and where it falls short, and then comes back to which camp is right and by how much. Every example in this article is Python 3, run by our team on Python 3.14.6 on 1 October 2026, with the actual output shown.
What is Object-Oriented Programming (OOP)?
OOP is a programming paradigm that treats a program as a collection of objects. Each object holds its own data, called attributes, and the behaviour that works on that data, called methods (functions that live inside a class).
The Python Tutorial on Classes describes a class as a way of bundling data and functionality together, and says that creating a new class creates a new type of object, from which you can make as many instances as you like. Put simply, instead of variables scattered across a file and a separate set of functions chasing after them, OOP keeps the things that belong together in one box.
Many languages support OOP, including Java, C#, C++, Python and JavaScript, but they do not all do it the same way. MDN points out that in JavaScript we often create objects without any class definition at all, and that the prototype mechanism underneath behaves less like inheritance and more like delegation.
Class vs object in OOP: what is the difference?
Picture one cookie cutter and a few cookies on a baking sheet. The cookie cutter is the class. It decides the shape every cookie will have, but you cannot eat it. Each cookie is an object: the real thing, made from the class. They all come from the same cutter, yet each one can be topped with a different flavour.
class Cookie:
def __init__(self, flavor):
self.flavor = flavor
def describe(self):
return f"A {self.flavor} cookie"
a = Cookie("chocolate")
b = Cookie("butter")
print(a.describe())
print(b.describe())
print(type(a).__name__, a is b)Output when we ran it:
A chocolate cookie
A butter cookie
Cookie FalseReading it piece by piece:
class Cookie: declares the class, the cutter. No cookie exists yet on this line.
__init__: the constructor (the function that runs when an object is created), which sets each cookie's starting values.
self.flavor: an attribute that each object keeps for itself.
Cookie("chocolate"): creates one actual object.
The last line confirms two things. Both cookies are of type Cookie, but a is b is False, so they are separate objects and their data really is kept apart.
A class describes what something will look like. An object is the thing actually built from that description.
What are the 4 principles of OOP? Examples for each
The principles most often named as the core of OOP are Encapsulation, Inheritance, Polymorphism and Abstraction. Each one solves a different problem, so we will take them one at a time, each with a short example you can run.
What is encapsulation?
MDN defines encapsulation as keeping an object's internal state private and drawing a clear line between its public interface, which others may call, and its private internals, which they should leave alone.
class BankAccount:
def __init__(self):
self._balance = 0
def deposit(self, amount):
if amount <= 0:
raise ValueError("amount must be positive")
self._balance += amount
@property
def balance(self):
return self._balance
acc = BankAccount()
acc.deposit(500)
print(acc.balance)
try:
acc.deposit(-100)
except ValueError as e:
print("ValueError:", e)
print(acc.balance)500
ValueError: amount must be positive
500The balance can only change through deposit(), which checks that the amount is positive, so a negative deposit never gets in. One thing worth knowing: Python does not enforce this strictly. The Python docs state plainly that private instance variables that cannot be accessed from outside an object do not exist in Python. A leading underscore, as in _balance, is only a shared convention meaning "hands off". Languages like Java have a private keyword that the compiler enforces.
What is inheritance?
Inheritance means building a new class on top of an existing one. The child class gets the parent's attributes and methods straight away and can add its own.
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
return f"{self.name} is eating"
class Dog(Animal):
def bark(self):
return f"{self.name}: Woof!"
d = Dog("Lucky")
print(d.eat())
print(d.bark())
print(isinstance(d, Animal))Lucky is eating
Lucky: Woof!
TrueDog never defines eat(), yet it can call it because it inherits it from Animal. And isinstance(d, Animal) returns True: as far as the program is concerned, this dog also counts as an animal.
What is polymorphism?
MDN describes polymorphism as a method having the same name but a different implementation in different classes. The payoff is that the calling code does not need to know which kind of object it is talking to.
class Dog:
def speak(self):
return "Woof"
class Cat:
def speak(self):
return "Meow"
for pet in [Dog(), Cat()]:
print(type(pet).__name__, pet.speak())Dog Woof
Cat MeowThe for loop calls speak() the same way every time. If you later add a Bird class with its own speak(), this loop works immediately without changing a single line. Notice that this example uses no inheritance at all. In Python, having a method with the matching name is enough.
What is abstraction?
Abstraction means hiding details the user does not need and exposing only what a thing can do. A steering wheel lets you turn the car without knowing how the steering system underneath works. In Python you can express this with the abc module, whose documentation states that a class with abstract methods cannot be instantiated until all of those methods are overridden.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
...
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
print(Square(3).area())
try:
Shape()
except TypeError as e:
print("TypeError:", e)9
TypeError: Can't instantiate abstract class Shape without an implementation for abstract method 'area'Shape only says "every shape must be able to compute its area", not how. Anyone who tries to create Shape() directly gets a TypeError straight away, which forces everyone on the team to write child classes that keep the same contract.
What are the benefits of OOP?
Organised code: data and behaviour for one concept live in one class, so when you hunt a bug you know which file to open.
Protected data: encapsulation routes every change through a checkpoint, like the negative-deposit check above.
Reuse: inheritance saves you from writing the same parts again and again.
Extension without edits: polymorphism lets you add new types while the calling code stays the same.
Easier teamwork: abstraction lets people agree on an interface and then build the internals separately.
These benefits show up more clearly as a project grows. If you want to keep going on writing code that stays readable, see 7 Techniques for Clean Code to Achieve Quality Code.
OOP is not always the answer: limits worth knowing
The "OOP is outdated" camp is not arguing from nothing. The most common problem is inheritance stacked many levels deep, where changing one parent class breaks child classes far away from it. The Python docs themselves explain that a base-class method calling another method of the same class may end up calling a version that a derived class has overridden, which can surprise you.
The fix many developers reach for is composition. Instead of saying a car is a kind of engine, you say a car has an engine. The idea goes back at least to the 1994 book Design Patterns by Gamma and colleagues, which recommends preferring object composition to class inheritance.
class Engine:
def start(self):
return "engine on"
class Car:
def __init__(self, engine):
self.engine = engine
def drive(self):
return f"{self.engine.start()}, car moving"
print(Car(Engine()).drive())engine on, car movingWant an electric motor instead? Pass in a different object that has a start() method, with no inheritance chain to tear apart. Go goes even further. Asked whether Go is an object-oriented language, the Go FAQ answers "Yes and no": Go has types and methods but no type hierarchy and no inheritance, and uses interfaces instead. To see what that looks like in practice, read JS2GO EP.16 Methods and Interfaces in Go vs JavaScript.
One more limit: small jobs rarely need OOP. A 30-line script that reads a file and totals some numbers is easier to read as two or three functions than wrapped in five classes.
OOP vs functional programming: how do they differ?
Functional Programming (FP) is a style built around functions that take input and return output, trying not to modify existing data. OOP, by contrast, has objects hold data and change their own state through methods.
OOP: suits systems with many kinds of "things" whose state changes over time, such as game characters, user accounts or UI screens.
FP: suits step-by-step data transformation, such as filtering, sorting and then summarising a list of orders.
In real work the two are not cut apart. Python and JavaScript both let you mix them in the same file. If you are still deciding which language to start with, read JavaScript vs Python: Which Language Should Beginners Start With? If you already write JavaScript, TypeScript adds interfaces and types that make the abstraction ideas in this article far more practical. And once OOP clicks and you want to see how developers arrange classes into proven shapes, continue with Design Patterns for beginners.
Summary: does OOP still matter?
The straight answer: both camps are half right. OOP is still a foundation worth learning, because many of the languages and frameworks you will meet at work are built around classes, and if you cannot read classes and objects you cannot read your team's code. But OOP is not the only answer. Deep inheritance causes real problems, and small jobs are fine as plain functions.
Do not worry if all 4 principles have not clicked on the first read. That is normal for everyone. Copy the cookie example and run it yourself, then add a new attribute like size or create a child class ChocolateChipCookie. Breaking the code and fixing it yourself once teaches more than rereading a definition ten times.
Follow more articles and tips for people starting out as programmers on our channels.
Facebook: Superdev Academy Thailand (https://www.facebook.com/superdev.academy.th)
YouTube: Superdev Academy Channel (https://www.youtube.com/@SuperdevAcademy)
Instagram: @superdevacademy (https://www.instagram.com/superdevacademy/)
TikTok: @superdevacademy (https://www.tiktok.com/@superdevacademy?lang=th-TH)
FAQ: Frequently Asked Questions about This Article
A collection of questions and answers to help you better understand the content of this article.