What is Object-Oriented Programming?

Object-Oriented Programming (OOP) is a programming paradigm that organises code around objects — self-contained units that bundle data (properties/fields) with the functions that operate on that data (methods). OOP contrasts with procedural programming, where code is organised as a sequence of functions that operate on separate data structures.

The key insight of OOP is modelling software around real-world entities. A BankAccount object knows its own balance and can deposit, withdraw, and check its balance. It protects its internal state from direct manipulation — you use its public methods, not poke at its internal fields.

AspectProceduralObject-Oriented
Code organisationFunctions + data structuresObjects (data + behaviour together)
Data accessGlobal or passed as parametersEncapsulated inside objects
Reuse mechanismFunction calls, includesInheritance, composition
Typical languagesC, Pascal, early PHP/PythonJava, C#, Python, PHP, JavaScript
Best forScripts, utilities, systems codeLarge, complex, long-lived applications

Classes and Objects

A class is a blueprint that defines what properties and methods an object will have. An object is a specific instance of that class — created with the new keyword in most languages.

Java — class and object // Class definition (blueprint) public class Car { private String colour; // field private int speed; // field public Car(String colour) { // constructor this.colour = colour; this.speed = 0; } public void accelerate(int amount) { // method this.speed += amount; } public int getSpeed() { return this.speed; } } // Creating objects (instances) Car myCar = new Car("red"); Car yourCar = new Car("blue"); myCar.accelerate(60); System.out.println(myCar.getSpeed()); // 60 System.out.println(yourCar.getSpeed()); // 0 — separate instance
Python — same concept class Car: def __init__(self, colour): self.colour = colour self._speed = 0 # _ prefix = convention for "private" def accelerate(self, amount): self._speed += amount def get_speed(self): return self._speed my_car = Car("red") my_car.accelerate(60) print(my_car.get_speed()) # 60

Pillar 1: Encapsulation

Encapsulation bundles data and methods into a single unit (the class) and restricts direct access to internal state. The object exposes a controlled public interface — while hiding implementation details.

Why it matters: Without encapsulation, any code can reach in and change account.balance = -99999 directly. With encapsulation, you call account.withdraw(amount) which validates the amount first.

Encapsulation — BankAccount example public class BankAccount { private double balance; // private — not directly accessible public void deposit(double amount) { if (amount <= 0) throw new IllegalArgumentException("Amount must be positive"); this.balance += amount; } public void withdraw(double amount) { if (amount > this.balance) throw new IllegalStateException("Insufficient funds"); this.balance -= amount; } public double getBalance() { return this.balance; } // controlled read access } // External code CANNOT do: account.balance = -9999 (compile error) // It must use the public methods which enforce rules

Access Modifiers

Most OOP languages provide: private (accessible only within the class), protected (accessible within the class and subclasses), public (accessible from anywhere). Use the most restrictive access level that works — default to private for fields.

Pillar 2: Inheritance

Inheritance allows a child class to reuse and extend the behaviour of a parent class. The child class inherits all non-private fields and methods, and can add new ones or override existing ones.

Inheritance example // Parent class public class Animal { protected String name; public Animal(String name) { this.name = name; } public void eat() { System.out.println(name + " is eating"); } public void sleep() { System.out.println(name + " is sleeping"); } } // Child class inherits from Animal public class Dog extends Animal { public Dog(String name) { super(name); } // call parent constructor public void bark() { System.out.println(name + " says: Woof!"); } @Override public void eat() { // override parent method System.out.println(name + " is eating dog food"); } } Dog rex = new Dog("Rex"); rex.eat(); // "Rex is eating dog food" (overridden) rex.sleep(); // "Rex is sleeping" (inherited from Animal) rex.bark(); // "Rex says: Woof!" (Dog-specific)

Pillar 3: Polymorphism

Polymorphism means "many forms" — the same method name behaves differently depending on the object's actual type. This allows you to write code that works with a general type (Animal) and have the correct specific behaviour invoked at runtime.

Polymorphism — runtime dispatch public class Cat extends Animal { public Cat(String name) { super(name); } @Override public void eat() { System.out.println(name + " is eating cat food"); } } // Polymorphic usage — loop over mixed Animal types Animal[] animals = { new Dog("Rex"), new Cat("Whiskers"), new Dog("Buddy") }; for (Animal a : animals) { a.eat(); // correct eat() method called based on ACTUAL type } // Output: // Rex is eating dog food // Whiskers is eating cat food // Buddy is eating dog food

Polymorphism eliminates if/else chains like if (animal instanceof Dog) { dog.eatDogFood(); } else if (animal instanceof Cat) {...}. The correct method is dispatched automatically.

Pillar 4: Abstraction

Abstraction means exposing only the essential features of an object while hiding the complex implementation details. This is achieved through abstract classes and interfaces.

Abstraction with interface (Java) interface Shape { double area(); // no implementation — just the contract double perimeter(); // implementors must provide these } class Circle implements Shape { private double radius; public Circle(double r) { this.radius = r; } @Override public double area() { return Math.PI * radius * radius; } @Override public double perimeter() { return 2 * Math.PI * radius; } } class Rectangle implements Shape { private double w, h; public Rectangle(double w, double h) { this.w = w; this.h = h; } @Override public double area() { return w * h; } @Override public double perimeter() { return 2 * (w + h); } } // Code that works with any Shape — doesn't need to know the type void printArea(Shape s) { System.out.println("Area: " + s.area()); }

Inheritance vs Composition

One of the most debated OOP design decisions is inheritance versus composition. Both are valid but serve different purposes:

PropertyInheritance (is-a)Composition (has-a)
RelationshipDog IS-A AnimalCar HAS-A Engine
CouplingTight — child depends on parentLoose — components are independent
FlexibilityLess flexible — hierarchy is fixedHighly flexible — swap components
Code reuseAutomatic through inheritance chainExplicit — delegate to composed objects
TestingHarder — must test full hierarchyEasier — test each component in isolation
When to useGenuine is-a, stable hierarchyPrefer this in most cases

Avoid Deep Inheritance Hierarchies

Hierarchies deeper than 2-3 levels become difficult to reason about and maintain. When you find yourself writing Animal → Mammal → Pet → DomesticAnimal → Dog → PoliceDog chains, reconsider using composition instead. Changes to the top of the hierarchy ripple unpredictably down.

Abstract Classes vs Interfaces

PropertyAbstract ClassInterface
Can have concrete methodsYesJava 8+: default methods; traditionally no
Can have fieldsYesOnly constants (static final)
ConstructorYesNo
Multiple inheritanceOne only (extends)Multiple (implements many interfaces)
Use whenShared code among related classesDefine a contract for unrelated classes
ExampleAbstractBaseView with render logicSerializable, Comparable, Printable

How We Research and Update This Guide

We test the underlying formula or workflow, compare outputs with reliable references, and revise examples whenever the page content changes.

  • The workflow or formula is tested directly in the tool and compared against independent reference examples.
  • Examples are kept practical so readers can verify the result without hidden assumptions.
  • Pages are revised whenever the interface, calculation flow, or surrounding guidance materially changes.

Frequently Asked Questions — OOP Concepts