OOP Concepts Explained: Object-Oriented Programming in Java and Python
OOP concepts explained simply: classes, objects, encapsulation, inheritance, polymorphism and abstraction, with one analogy and runnable Java and Python.
20+ years shipping production systems from the metal up. Everything here is grounded in real deployments.
- ✓Basic variables and functions in any language
- OOP organises a program as objects: data plus the functions (methods) that act on it.
- A class is the blueprint; an object is one thing built from it.
- Encapsulation: an object guards its own data and exposes safe operations.
- Inheritance: a new class reuses an existing one and changes only what differs.
- Polymorphism: one call, such as cook(), behaves correctly for each kind of object.
- Abstraction: callers depend on what an object can do, not how it does it.
Think of a restaurant kitchen. A recipe describes what a dish contains and how it's made; that's a class. Each plate that actually comes out of the kitchen is an object made from the recipe. The kitchen door keeps customers from wandering in and changing things (encapsulation). A pastry chef is still a chef, with the same basics plus a speciality (inheritance). When the head chef shouts "cook!", every chef makes their own dish (polymorphism). And the menu tells you what you can order without explaining how the kitchen works (abstraction).
Most beginners meet object-oriented programming as a list of four scary words. They're simpler than they sound. OOP is just a way to keep related data and behaviour together, so a large program stays understandable as it grows. This guide explains every idea with one running analogy, a restaurant kitchen, then shows each one in a few lines of Python, and finally all four together in Java. No prior OOP knowledge is assumed: if you can write a function and a variable, you can follow along.
OOP in One Sentence
Object-oriented programming means building a program out of objects, where each object holds some data and knows how to do things with it. Compare that with a purely procedural style, where data sits in variables and separate functions pass it around. Both work. OOP pays off when a program models many related things (users, orders, payments, chefs) and you want each one's rules to live in one place.
Almost every mainstream language supports OOP: Java and C# are built around it, Python, JavaScript, PHP and C++ support it alongside other styles.
Classes and Objects: The Recipe and the Dish
A class is a blueprint. It says what data every object of that kind has (its attributes) and what it can do (its methods). An object, also called an instance, is one concrete thing built from the class, with its own values.
Below, Dish is the recipe. pasta and salad are two separate objects made from it. They share the same structure and methods, but each keeps its own name and price.
pasta.describe() runs describe with self set to pasta.Encapsulation: The Kitchen Door
Encapsulation means an object protects its own data and only lets the outside world change it through methods that enforce the rules. Customers can order food, but they can't walk into the kitchen and change the recipe.
Here an Order keeps its list of items internal. The only way to add an item is add(), which rejects negative prices, and the total is read-only because it's always calculated from the items.
Inheritance: A Pastry Chef Is Still a Chef
Inheritance lets a new class (the child or subclass) start from an existing one (the parent or base class). The child gets everything the parent has and only adds or changes what's different. A pastry chef greets people like any chef but cooks something different.
Use inheritance only for a true 'is a' relationship: a PastryChef is a Chef. If you're tempted to inherit just to reuse a few methods, composition (one object holding another) is usually the better choice.
Polymorphism: Everyone Responds to "Cook"
Polymorphism means 'many forms': the same method call does the right thing for each kind of object. The head chef shouts "cook!" once, and every chef makes their own dish. The code giving the order doesn't need to know which kind of chef it's talking to.
This is what removes long if/elif chains that check an object's type. Add a new kind of chef with its own cook() method and the loop below keeps working without a single change.
Abstraction: The Menu Hides the Kitchen
Abstraction means depending on what something can do, not how it does it. A menu lists dishes without explaining the cooking. In code, an abstract base class (or an interface in Java) defines the methods every implementation must provide, and the rest of the program works only with that contract.
Below, checkout() accepts any PaymentMethod. It doesn't know or care whether it's a card or cash. The abstract class itself can't be created, which forces every real payment type to implement pay().
All Four Pillars Together in Java
Java makes the same ideas explicit with keywords: interface for abstraction, private for encapsulation, extends for inheritance and @Override for polymorphism. This small kitchen uses all four in one file.
When OOP Is the Wrong Tool
OOP isn't always the best fit. A short script that reads a file and prints a report is clearer as a few functions. Data transformations, such as cleaning a list of records, are often simpler in a functional style with plain functions and immutable data. Overusing OOP shows up as classes with one method, getters and setters for everything, and deep inheritance trees that make a small change ripple everywhere.
A good rule: introduce a class when you have data and behaviour that genuinely belong together, or several kinds of thing that share a contract. Otherwise, a function is fine.
The New Customer Type Nobody's Code Knew About
discount() method, all sharing a common base class. Checkout now calls customer.discount() and never checks the type, so a new type only needs one new class.- Repeated if/elif chains on a 'type' field are a sign the code wants polymorphism.
- Keep behaviour next to the data it belongs to, so there's one place to change.
- A base class with a required method turns a forgotten case into an immediate error instead of a silent wrong answer.
| File | Command / Code | Purpose |
|---|---|---|
| classes.py | class Dish: | Classes and Objects |
| encapsulation.py | class Order: | Encapsulation |
| inheritance.py | class Chef: | Inheritance |
| polymorphism.py | class Chef: | Polymorphism |
| abstraction.py | from abc import ABC, abstractmethod | Abstraction |
| Kitchen.java | public class Kitchen { | All Four Pillars Together in Java |
Key takeaways
Common mistakes to avoid
4 patternsThinking OOP means 'put everything in a class'
Using inheritance just to reuse code
Checking types with if/elif instead of using polymorphism
Confusing a class with an object
Interview Questions on This Topic
What are the four pillars of OOP? Explain each in one sentence.
Frequently Asked Questions
20+ years shipping production systems from the metal up. Everything here is grounded in real deployments.
That's Software Engineering. Mark it forged?
3 min read · try the examples if you haven't