Blog Java Oops

Object Oriented Programming : Polymorphism, Abstraction, Encapsulation, and Inheritance

There are four fundamental concepts of Object Oriented Programming (OOP) in Java.

1. Polymorphism

In Object Oriented Programming, Polymorphism allows objects of different classes to be treated as objects of a common superclass. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object. It enables one interface to be used for a general class of actions.

Example: Consider a real-world scenario where we have a generic payment method interface, and we implement this interface for various payment types like CreditCardPayment and PayPalPayment. For more details on polymorphism, see our section on Polymorphism in Action.

Java
interface Payment {
    void pay(int amount);
}

class CreditCardPayment implements Payment {
    public void pay(int amount) {
        System.out.println("Paying with Credit Card: " + amount);
    }
}

class PayPalPayment implements Payment {
    public void pay(int amount) {
        System.out.println("Paying with PayPal: " + amount);
    }
}

public class PaymentProcessor {
    public static void main(String[] args) {
        Payment payment = new CreditCardPayment();
        payment.pay(100);

        payment = new PayPalPayment();
        payment.pay(200);
    }
}

If you want to learn more about Polymorphism in object orient programing, please follow the link for detail explaination,

2. Abstraction

Abstraction in Oops

In Object Oriented Programming, Abstraction means hiding the complex implementation details and showing only the necessary features of an object. In Java, abstraction is achieved using abstract classes and interfaces.

Example: Consider a vehicle system where we define a generic Vehicle class with a method start(). The implementation of start() is abstracted and provided by the subclasses.

Java
abstract class Vehicle {
    abstract void start();
}

class Car extends Vehicle {
    void start() {
        System.out.println("Car starts with a key.");
    }
}

class Motorcycle extends Vehicle {
    void start() {
        System.out.println("Motorcycle starts with a button.");
    }
}

public class VehicleTester {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Output: Car starts with a key.

        Vehicle myMotorcycle = new Motorcycle();
        myMotorcycle.start(); // Output: Motorcycle starts with a button.
    }
}

Abstraction is a fundamental concept in Object-Oriented Programming (OOP) because it helps manage complexity by hiding unnecessary details from the user. This concept is crucial for several reasons:

  1. Simplicity: Abstraction allows programmers to focus on the interface towards the user rather than the complex inner workings of a class. By providing a simpler view, it makes the programming process more manageable and reduces cognitive load. This is akin to how you only need to know how to start a car using the ignition and do not need to understand the complex mechanisms of the engine and transmission systems to drive.
  2. Modularity: It helps in separating the contract of what a class (or a set of classes) does from how it accomplishes it. This separation is crucial for modular design, allowing developers to work on parts of the system independently or to reuse existing abstractions without understanding all their internals.
  3. Maintainability: Since the implementation details are hidden, changes to the implementation do not affect the code that uses these abstractions. This means that improvements, optimizations, or fixes can be made to the internals of a class without requiring changes to the code that utilizes it, making the system easier to maintain.
  4. Reusability: Abstraction enables higher levels of reuse by allowing the same interface to be implemented in multiple ways. For example, the same interface for a storage system could be implemented for different types of underlying storage technologies (like hard drives, SSDs, or cloud storage) without changing the way the storage is used in the application.
  5. Scalability: With the help of abstraction, you can scale your application architecture by building more abstract layers on top of existing ones. This can help in developing complex systems from simple components by abstracting functionality at each level.
  6. Interchangeability: Since specific implementations are decoupled from the rest of the application, it’s easier to replace one implementation with another. This can be particularly useful when new technologies or improvements become available, allowing their integration with minimal changes to the overall system.

In the example of a vehicle system, abstraction allows a programmer to define a general concept of a vehicle that has a start method without specifying how each type of vehicle starts.

This could mean electric cars start differently from gasoline cars, but the action of starting the car remains consistent from the driver’s perspective. This approach not only simplifies the design but also enables future vehicle types to be added to the system with minimal changes to the existing codebase.

3. Encapsulation

In Object Oriented Programming, Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. It is a way to protect the data from outside interference and misuse.

Example: Consider a BankAccount class that encapsulates the balance and provides methods to deposit and withdraw money safely.

Java
class BankAccount {
    private int balance;

    public BankAccount(int initialBalance) {
        this.balance = initialBalance;
    }

    public void deposit(int amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    public void withdraw(int amount) {
        if (amount > 0 && balance >= amount) {
            balance -= amount;
        }
    }

    public int getBalance() {
        return balance;
    }
}

public class AccountTester {
    public static void main(String[] args) {
        BankAccount account = new BankAccount(1000);
        account.deposit(500);
        account.withdraw(200);
        System.out.println("Current balance: " + account.getBalance());
    }
}

Each of these examples illustrates the core principles of OOP in a way that relates to real-world scenarios, helping to understand how these concepts enable more efficient, organized, and reusable code.

4. Inheritance

Inheritance is an OOP concept where one class can inherit the fields and methods of another class. The class which inherits the properties of another is known as the subclass (or derived class), and the class whose properties are inherited is known as the superclass (or base class). Inheritance promotes code reusability and establishes a relationship between different classes through their objects.

Example: Consider an example of a generic Vehicle class (superclass) and specific types of vehicles like Car and Bike (subclasses) that inherit from it.

Java
// Superclass
class Vehicle {
    protected String brand = "Ford";        // Vehicle attribute

    // Vehicle method
    public void honk() {                    
        System.out.println("Tuut, tuut!");
    }
}

// Subclass
class Car extends Vehicle {
    private String modelName = "Mustang";    // Car attribute

    public static void main(String[] args) {
        // Create a myCar object
        Car myCar = new Car();

        // Call the honk() method (from the Vehicle class) on the myCar object
        myCar.honk();

        // Display the value of the brand attribute (from the Vehicle class) and the modelName from the Car class
        System.out.println(myCar.brand + " " + myCar.modelName);
    }
}

In this example, Car extends Vehicle. This means that Car inherits all of the fields and methods of Vehicle, plus any additional fields and methods defined in Car. The Car the class has its attribute modelName, but it also inherits the brand attribute and the honk() method from Vehicle. When you run the Car class, it displays the brand and model name of the car and uses the honk() method inherited from Vehicle.

  • Inheritance allows a class to use the fields and methods of another class. This promotes code reusability and establishes a parent-child relationship between classes.
  • The subclass inherits all public and protected fields and methods from the superclass, along with any default modifiers (no modifier). However, it does not inherit the private members of the superclass.
  • Inheritance represents an “is-a” relationship between two classes (e.g., a Car is a Vehicle).

With encapsulation, abstraction, and polymorphism, inheritance enables developers to build complex systems more efficiently by reusing and extending existing code.

Differene between Encapsulation and abstraction

Encapsulation and abstraction are two fundamental concepts in object-oriented programming (OOP), but they serve different purposes. Let’s explore the differences between encapsulation and abstraction:

Encapsulation:

  1. Encapsulation is the mechanism of wrapping data (attributes) and functions (methods) that operate on the data within a single unit, i.e., a class.
  2. It is about hiding the internal details of an object and providing a public interface to interact with the object.
  3. Encapsulation focuses on the “how” aspect, i.e., how the data is stored and how the methods operate on that data.
  4. It provides data protection by restricting direct access to the internal state of an object from outside the class. Access to the data is typically controlled through getter and setter methods.
  5. Encapsulation helps in achieving data integrity, security, and maintainability by controlling access to the internal state of an object.
  6. It promotes the concept of data hiding, where the internal representation of an object is hidden from the outside world.
  7. Example: In a class representing a bank account, the account balance can be encapsulated by making it a private variable and providing public methods like deposit() and withdraw() to modify the balance.

Abstraction:

  1. Abstraction is the process of simplifying complex systems by breaking them down into smaller, more manageable parts.
  2. It focuses on creating a simplified view of an object or system by showing only the essential features and hiding the unnecessary details.
  3. Abstraction deals with the “what” aspect, i.e., what an object does, rather than how it does it.
  4. It helps in managing complexity by providing a high-level view of the system and hiding the low-level implementation details.
  5. Abstraction is achieved through abstract classes and interfaces, which define a common structure and behavior for the derived classes.
  6. It allows the user to focus on using the object’s functionality without worrying about the internal complexities.
  7. Example: In a shape hierarchy, you can have an abstract base class called Shape that defines common properties and methods for all shapes. The specific details of each shape (e.g., area calculation) can be abstracted away in the derived classes like Circle, Rectangle, etc.

Key Differences:

  • Encapsulation is about hiding the internal details and protecting data, while abstraction is about simplifying complex systems and showing only the essential features.
  • Encapsulation focuses on the implementation and data protection, while abstraction focuses on the design and providing a high-level view.
  • Encapsulation is typically achieved through access modifiers (e.g., private, public) and getter/setter methods, while abstraction is achieved through abstract classes and interfaces.
  • Encapsulation helps in ensuring data integrity and security, while abstraction helps in managing complexity and providing a clear interface for interaction.

In summary, encapsulation and abstraction are both important concepts in OOP, but they serve different purposes. Encapsulation is about data protection and hiding internal details, while abstraction is about simplifying complex systems and providing a high-level view. They complement each other in building well-structured and maintainable object-oriented systems.

Discover how to master object-oriented programming in Java by getting your copy of [Mastering Java – A Comprehensive Guide to Object-Oriented Programming] today!

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over