A Dive into OOP Concepts 😺 with Examples

You might have already using OOP concepts without knowing it! So here I am, to share my learnings on this topic OOP.
Exactly an year ago, I published a blog “A Look into SOLID principles with Examples”. It reached many people, so I am going to follow the same format.
In some example I would have added cross-reference to the SOLID Principles blog.
This blog assumes that you have a basic understanding of Classes and Objects in at-least one language. But but I’ll use Java as an example here for every concept.
As you might know we have four pillars for OOP.
Abstraction
Encapsulation
Inheritance
Polymorphism
These pillars will help use to write maintainable code with less hassle. But as like other principles overusing may affect your code in the worst way possible.
We will go into the pillars one by one and learn the concept with an example.
Important thing to remember: Some concepts are interlinked to each other, so you cannot learn without overlapping with others. Some are totally different from others.
Abstraction
Abstraction hides information that is not relevant to the context or rather shows only relevant information and simplifies
In Simple words, Abstraction means hide away the complexity and show only required things.
In even Simple words, Hiding for Simplicity.
Did you noticed, I just explained Abstraction by using Abstraction.
Example:
interface Operator {
void switchOn();
void switchOff();
}
class PackagingOperator implements Operator {
private boolean onStatus;
public void switchOn() {
onStatus = true;
sendNotification();
}
public void switchOff() {
onStatus = false;
sendNotification();
}
private void sendNotification() {
// Send Mail about the status
}
}
In this example, Operator
interface only says about two functions switchOn
& switchOff
. It doesn’t have any other functions related to how switching on, or switching off.
This overlaps with Dependency Inversion Principle
(DIP) from SOLID principles. As using only an Interface or Abstract class (in align with DIP principle) helps to achieve Abstraction.
Key Points:
Hides for Simplicity
Focuses on what an object does, not how it does it.
Mostly uses abstract class, interface to define methods.
It doesn’t have the full implementation, so we need some concrete classes to provide logic.
It hides complex behavior behind a simplified interface.
Encapsulation
Wrapping data and methods within classes in combination with implementation hiding (through access control) is often called encapsulation.
Here also we will hide things but for different purpose, Safety and Security.
We will hide the data and methods using access modifiers (private, public).
Let’s take the previous example,
class PackagingOperator implements Operator {
private boolean onStatus;
public void switchOn() {
onStatus = true;
sendNotification();
}
public void switchOff() {
onStatus = false;
sendNotification();
}
private void sendNotification() {
// Send Mail about the status
}
}
Here the onStatus
, sendNotification()
is hidden using private.
Another simple example would be an POJO class, User.
class User {
private String name;
private Long dateOfBirth; // Timestamp in seconds
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
int age = ... - dateOfBirth;// Do some calculation with dateOfBirth value
return age;
}
public void setAge(int age) {
Long dateOfBirth = ... - age; // Do some calculation with age value
this.dateOfBirth = dateOfBirth;
}
}
Here I restricted the direct access to name by defining public getters and setters. That looks like a unnecessary methods until you analyze what I did in the case of age.
There is no age
variable, instead I am calculating the age from dateOfBirth
long variable. (Because that’s how real-world works, you won’t store age, you store DOB to calculate Age anytime). Even I restricted direct access to dateOfBirth
.
Key Points:
Hides for Security
Hiding the state or internal representation of an object for safety
Uses access modifiers to restrict direct access to fields and expose behavior through controlled methods.
Inheritance
Mechanism by which one class acquires the properties and behaviors of the parent class
You can think of it like extending a class but without modifying it. (Seems like its supporting the Liskov Substitution Principle — LSP).
Example:
abstract class Vehicle {
String brand;
Vehicle(String brand) {
this.brand = brand;
}
void move() {
System.out.println(brand + " is moving.");
}
// Abstract method: must be implemented by subclasses
abstract void startEngine();
}
class Car extends Vehicle {
int wheels;
Car(String brand, int wheels) {
super(brand);
this.wheels = wheels;
}
@Override
void startEngine() {
System.out.println(brand + " car engine started with key.");
}
void fuelType() {
System.out.println(brand + " uses petrol or diesel.");
}
}
class ElectricCar extends Car {
int batteryCapacity;
ElectricCar(String brand, int wheels, int batteryCapacity) {
super(brand, wheels);
this.batteryCapacity = batteryCapacity;
}
// Override startEngine to reflect electric behavior
@Override
void startEngine() {
System.out.println(brand + " electric car started silently.");
}
void chargeBattery() {
System.out.println(brand + " is charging: " + batteryCapacity + " kWh.");
}
}
Here Vehicle is an Abstract concept (Abstraction), Car inherits the move
method from Vehicle. Electric Car inherits all the methods from Car.
This is a “Is-A” relation. Eg: Electric Car is a Car, Car is a Vehicle.
Key Points:
Is-A relation
Mechanism to acquire all the properties from one class to another
Polymorphism
ability of a function to behave differently based on the context
Poly — Many, Morph — Forms = Many Forms
This can be classified into two:
Compile time (Static binding)
Run time (Dynamic binding)
This overlaps with Abstraction and Inheritance, Let’s see.
Compile Time Polymorphism:
When you declare functions with the same name in the same class (or Parent class), based on the input type the function that is called differs.
Example:
class PaymentProcessor {
public void pay(double amount) {
System.out.println("Paid ₹" + amount + " using default method.");
}
public void pay(double amount, String method) {
System.out.println("Paid ₹" + amount + " using " + method + ".");
}
public void pay(double amount, String method, String currency) {
System.out.println("Paid " + currency + amount + " using " + method + ".");
}
}
Here if you call pay
with single parameter, the first function is called.
If you call pay
with two parameters (types also should match or else compile error), second function is called. If you call pay with three parameters, last method is called.
This is also called Method overloading.
Run Time Polymorphism:
When you declare the same method as in parent class, based on the instance object the function is called.
Example:
class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows");
}
}
// Main function
Animal animal = new Animal();
animal.makeSound(); // Animal makes a sound
animal = new Dog();
animal.makeSound(); // Dog barks
animal = new Cat();
animal.makeSound(); // Cate meows
Here Dog and Cat overrides the method makeSound
but still the method is called based on the instance (Dog
or Cat
).
This is called Method Overriding.
Key Points:
the ability of a function to behave differently based on the context
Compile Time Polymorphism — Method Overloading
Run time Polymorphism — Method Overriding
Conclusion
Most of the principles overlaps, that’s because principles are to be supported by each other, so you apply one correctly, you are indirectly applying others.
If you have come this far, Thank you for reading this article.
Connect with me:
My Personal Portfolio: https://sanjaydev.tech
Sources:
Subscribe to my newsletter
Read articles from Sanjay S directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Sanjay S
Sanjay S
I am currently working as a Software Developer @Esko. I have been learning Android from past 3 years from my College doing trial and errors. I can say I have more experience in knowing errors than code. I have also developed web applications in React.