Procedural vs Object-Oriented Programming
A recipe is a list of steps: boil water, add rice, wait. That's procedural thinking: a program is a sequence of steps that work on data kept somewhere else. A restaurant kitchen works differently: the chef, the waiter and the cashier each own their own job and their own information, and they ask each other for things. That's object-oriented thinking. Both styles can solve the same problem; they differ in where the data lives and who protects it.
The Same Problem, Two Ways
public class AccountsOop {
static class Account {
private final String holder;
private long balance;
Account(String holder, long balance) {
this.holder = holder;
this.balance = balance;
}
boolean withdraw(long amount) {
if (amount <= 0 || amount > balance) return false;
balance -= amount;
return true;
}
String show() { return holder + ": Rs. " + balance; }
}
public static void main(String[] args) {
Account navika = new Account("Navika", 5000);
navika.withdraw(1200);
navika.withdraw(99999);
System.out.println(navika.show());
}
}public class AccountsProc {
static String[] holders = {"Navika"};
static long[] balances = {5000};
static boolean withdraw(int index, long amount) {
if (amount <= 0 || amount > balances[index]) return false;
balances[index] -= amount;
return true;
}
public static void main(String[] args) {
withdraw(0, 1200);
withdraw(0, 99999);
balances[0] = -50000; // nothing stops this line
System.out.println(holders[0] + ": Rs. " + balances[0]);
}
}Navika: Rs. 3800How it works
- In the procedural version, the data (
holders,balances) lives in shared arrays, and functions reach in by index. Thewithdrawfunction checks the rules, but line 14 skips it and sets a negative balance directly; nothing can stop it. - In the OOP version,
balanceis private: only theAccount's own methods can change it. The only way to take money out iswithdraw, which always checks the rules. - Both refuse the Rs. 99,999 withdrawal. Only the OOP version guarantees that no other code can bypass the check. (The output shown is from the OOP version.)
Try it yourself: add a deposit(long amount) method that refuses amounts of zero or less, then call navika.deposit(-500). Does the balance change?
One detail: here Account is nested inside AccountsOop so the example fits in one file, and Java lets code in the same file reach private fields. In a real project, Account lives in its own file, Account.java, and the compiler blocks navika.balance = -50000; from anywhere else. The lesson "Encapsulation in Java" covers this.
Side by Side
| Procedural | Object-oriented | |
|---|---|---|
| Program is organized around | Steps and functions | Objects (things) |
| Data lives | In shared variables, arrays or structures | Inside objects, usually private |
| Who enforces the rules | Every caller has to remember | The object itself |
| Adding a new kind of thing | Add more if checks in many functions | Add a new class (often through inheritance) |
| Good for | Short scripts, simple calculations, algorithms | Large systems that grow and change over years |
| Languages | C, early BASIC, shell scripts | Java, C#, Kotlin, and Python and C++ when used this way |
Java isn't against procedural code: a static method that adds up an array is perfectly fine. OOP shines when data has rules and many parts of a program use it.
Common Mistakes
Writing procedural code inside a class and calling it OOP. A class full of static methods working on public arrays is still procedural.
Making everything an object. A one-line calculation doesn't need a class of its own; a static method is fine.
Leaving fields public. That throws away OOP's main benefit, protecting the data.
Interview Corner
What is the difference between procedural and object-oriented programming?
Procedural programming organizes a program as a sequence of functions that operate on separate data, so any function can change the data. Object-oriented programming bundles data with the methods that operate on it inside objects, usually keeping the data private, so the object controls how it changes. OOP adds encapsulation, inheritance and polymorphism, which help large programs stay correct as they grow.
Practice
- Easy: List the data and the functions you'd need for a library book system in procedural style, then group them into classes.
- Harder: Add a
depositmethod to the OOPAccountthat refuses zero or negative amounts, and show thatmaincan't put a negative amount in.
Key Takeaways
Was this tutorial helpful?