OOP Concepts

Dhyani Yashora
Nerd For Tech
Published in
5 min readJul 10, 2024

Introduction to OOP Concepts

Object-Oriented Programming (OOP) is a way of designing and coding software by thinking in terms of “objects.” These objects represent real-world things or concepts, like a car, a bank account, or a person. Each object has its own data and actions it can perform.

There are four main ideas in OOP:

  1. Inheritance: This allows one class to inherit features (like properties and methods) from another class.
  2. Encapsulation: This means keeping an object’s data safe from outside interference and misuse.
  3. Polymorphism: This allows objects to be treated as instances of their parent class, even if they are actually instances of a child class.
  4. Abstraction: This means hiding the complex details of how something works and showing only the essential features.

Inheritance

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a new class to inherit attributes and methods from an existing class. The existing class is called the parent class or base class, and the new class is called the child class or subclass. This mechanism provides a way to create a new class by reusing the features of an existing class.

Why Use Inheritance?

  • Code Reusability: Can reuse code from existing classes, which reduces redundancy.
  • Hierarchical Relationships: It naturally models relationships between objects, like “A car is a type of vehicle.”
  • Maintenance: Easy to update and maintain code since changes in the parent class can affect all child classes.

Real-World Example: Imagine a company where all employees share some common attributes like name, ID, and department. However, different types of employees (like managers, engineers, and interns) also have specific attributes and behaviors. Instead of redefining common attributes and behaviors in every employee type, you can create a base class “Employee” and have different types of employees inherit from it.

// Parent class
class Vehicle {
String make;
String model;

Vehicle(String make, String model) {
this.make = make;
this.model = model;
}

void start() {
System.out.println("The " + make + " " + model + " is starting.");
}
}

// Child class inheriting from Vehicle
class Car extends Vehicle {
int doors;

Car(String make, String model, int doors) {
super(make, model);
this.doors = doors;
}

void drive() {
System.out.println("The " + make + " " + model + " with " + doors + " doors is driving.");
}
}

// Usage
public class Main {
public static void main(String[] args) {
Car myCar = new Car("Toyota", "Camry", 4);
myCar.start();
myCar.drive();
}
}

Encapsulation

Encapsulation is the concept of bundling data (attributes) and methods (functions) that operate on the data into a single unit called a class. It also involves restricting direct access to some of the object’s components, making the internal state of the object hidden from the outside world. This is achieved using access modifiers like private and protected attributes.

Why Use Encapsulation?

  • Data Protection: Prevents unauthorized access and modification of data.
  • Modularity: Each object manages its own state information, making the system easier to understand and manage.
  • Abstraction: Hides complex implementation details and exposes only the necessary parts.

Real-World Example: Consider a real-world “Bank Account” where the balance should not be directly accessed or modified from outside the class. Instead, deposits and withdrawals should be done through methods that ensure the balance is updated correctly and no invalid transactions are made.

class BankAccount {
private String owner;
private double balance;

public BankAccount(String owner, double balance) {
this.owner = owner;
this.balance = balance;
}

public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited " + amount + ". New balance is " + balance);
} else {
System.out.println("Invalid deposit amount.");
}
}

public void withdraw(double amount) {
if (0 < amount && amount <= balance) {
balance -= amount;
System.out.println("Withdrew " + amount + ". New balance is " + balance);
} else {
System.out.println("Insufficient funds or invalid amount.");
}
}

public double getBalance() {
return balance;
}
}

// Usage
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount("John Doe", 100);
account.deposit(50);
account.withdraw(30);
System.out.println("Balance: " + account.getBalance());
}
}

Polymorphism

Polymorphism, meaning “many shapes,” allows objects of different classes to be treated as objects of a common super class. It enables methods to do different things based on the object it is acting upon, even though they share the same name. This can be achieved through method overriding and method overloading.

  • Method Overriding: A child class provides a specific implementation of a method that is already defined in its parent class.
  • Method Overloading: Methods have the same name but different parameters within the same class.

Why Use Polymorphism?

  • Flexibility: It allows a single interface to represent different underlying forms (data types).
  • Simplified Code: Reduces complexity by allowing the same method name to be used for different types of actions.

Real-World Example: A man is acting in different roles like an employer in the office, a passenger in the bus, a child for parents, a husband for wife, and a father to children.

abstract class Shape {
abstract void draw();
}

class Circle extends Shape {
void draw() {
System.out.println("Drawing a circle");
}
}

class Square extends Shape {
void draw() {
System.out.println("Drawing a square");
}
}

class Triangle extends Shape {
void draw() {
System.out.println("Drawing a triangle");
}
}

// Usage
public class Main {
public static void main(String[] args) {
Shape[] shapes = {new Circle(), new Square(), new Triangle()};

for (Shape shape : shapes) {
shape.draw();
}
}
}

Abstraction

Abstraction is the process of hiding the complex implementation details and exposing only the necessary and relevant parts of an object. It simplifies interaction with the object by providing a clear and simple interface. Abstract classes and interfaces are used to achieve abstraction in OOP.

  • Abstract Class: A class that cannot be instantiated on its own and requires subclasses to provide implementations for its abstract methods.
  • Interface: A contract that defines a set of methods that must be implemented by a class.

Why Use Abstraction?

  • Simplification: Reduces complexity by hiding unnecessary details.
  • Focus on Essentials: Allows developers to focus on high-level operations without worrying about the underlying implementation.

Real-World Example: Think of using a TV remote. You can use buttons to change channels or adjust the volume without knowing the intricate details of how the TV processes these actions.

abstract class Animal {
abstract String sound();
}

class Dog extends Animal {
String sound() {
return "Bark";
}
}

class Cat extends Animal {
String sound() {
return "Meow";
}
}

// Usage
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();

System.out.println(dog.sound());
System.out.println(cat.sound());
}
}

Summary

  • Inheritance allows classes to inherit properties and methods from other classes.
  • Encapsulation restricts access to certain details of an object to promote modularity and reduce complexity.
  • Polymorphism allows methods to be used in different ways based on the object calling them.
  • Abstraction hides the complex reality while exposing only the necessary parts.

Thanks for reading and hope you enjoyed!

--

--

Dhyani Yashora
Nerd For Tech

Undergraduate at Faculty of Information Technology, University of Moratuwa, Sri Lanka