top

Search

Java Tutorial

.

UpGrad

Java Tutorial

Difference Between Data Hiding and Abstraction

Introduction

In the world of software development, two fundamental concepts play a crucial role in designing robust and maintainable code: data hiding and abstraction. While these concepts are related, they serve distinct purposes and offer unique benefits. OOP uses the ideas of data abstraction and data hiding to make systems less complex and more user-friendly by only displaying the information that is important to the end user and hiding the details that are not. In this article, we will delve into the differences between data hiding and abstraction, exploring their definitions, implementation, and practical examples.

Overview

Both data hiding and abstraction are essential principles in object-oriented programming (OOP) that contribute to building modular, scalable, and secure software systems. While they share similarities, it is important to understand their distinctions to make informed design decisions.

Abstraction is used to hide the internal implementation details of the code or software and show users only the most crucial set of services or features. On the other side, data hiding is a procedure that conceals internal data and prevents a program from directly accessing it for illegal access. Utilizing private and secured access specifiers allows for this.

What Is Abstraction?

Abstraction is a fundamental concept in OOP that focuses on representing complex systems by simplifying their complexity. It conceals the internal implementation and just emphasizes the services. The use of abstract classes and interfaces, along with their subsequent implementation, enable this. Only the essential qualities of an object set it apart from all other objects. Only the most crucial information is highlighted; the remainder is kept hidden from the user or reader.

It involves creating abstract classes, abstract methods, and interfaces to define common characteristics and behaviors shared by a group of related objects. Abstraction allows developers to model real-world scenarios and design flexible, reusable code.

Abstract Classes

An abstract class serves as a blueprint for derived classes and cannot be instantiated on its own. It provides common attributes and methods that subclasses inherit and implement. It must be inherited from or implemented by another class in order to be accessed. The abstract keyword creates an abstract class. It might or might not include abstract techniques. This enables code reusability and promotes a consistent structure across related objects.

Abstract Methods

A method that is declared without an implementation (without braces) and is followed by a semicolon is referred to as an abstract method. Abstract methods exist within an abstract class and do not have an implementation. Subclasses must provide a concrete implementation for these methods, ensuring adherence to the defined contract. Abstract methods enforce consistency while allowing flexibility in implementation. For example:

A class must be declared abstract if it contains abstract methods, for example:

abstract class Bird {
    // declare fields (if needed)
    // declare non-abstract methods (if needed)
    // declare the abstract method 'fly'
    abstract void fly();
}

The inherited class typically offers implementations for each of the abstract methods in the parent class when an abstract class is inherited. However, the inherited class must also be marked abstract if it does not implement every one of them.

Interfaces

Similar to a class, an interface is a reference type that can only contain nested types, constants, method signatures, default methods, and static methods. Interfaces define a set of method signatures that a class must implement. They serve as contracts, ensuring that classes that implement an interface adhere to a specific set of behaviors. 

They enable loose coupling and polymorphism, allowing objects to be treated interchangeably based on shared capabilities. Only default methods and static methods have a method body. Interfaces can only be extended by other interfaces or implemented by classes; they cannot be instantiated. The abstract modifier is not applied to the methods declared in interfaces since those that are not default or static are implicitly abstract.

We must create a class that implements the interface in order to use it.

public class operateKTMDuke implements operateMotorBike {

    // Implement the OperateMotorBike method signatures here
    int turn(Direction direction, double radius, double startspeed, double endspeed) {
        // Implement the logic for turning the motorbike here
        // You can use the provided parameters to control the turn
        // Return the result, possibly indicating success or failure
        return 0; // Placeholder return value, modify as needed
    }
    // Implement the signalTurn method
    public int signalTurn(Direction direction, boolean signalOn) {
        // Implement the logic for signaling a turn
        // You can use the provided parameters to determine the direction
        // and whether to turn the indicator lights on or off
        if (signalOn) {
            // Turn the corresponding indicator lights on
        } else {
            // Turn the corresponding indicator lights off
        }
        return 0; // Placeholder return value, modify as needed
    }
    // Other members and helper classes can be defined here
}

The abstract method signalTurn or turn is available in the interface, as we have seen in the examples above. However, the other class's implementation of the method hides it.

Abstraction Types

Abstraction can be categorized into three main types: procedural abstraction, data abstraction, and control abstraction. Each type focuses on abstracting specific aspects of a system to improve maintainability and modularity.

1. Procedural Abstraction

Procedural abstraction involves encapsulating a sequence of operations into a single function or method. The word itself contains a set of functions that are performed one after another in order to achieve abstraction through classes.

It is an example of what a subprogram should accomplish. It offers methods for designating well-defined actions or procedures as entities. It promotes code reuse, readability, and simplifies complex operations.

Data Abstraction

Data abstraction focuses on exposing the essential properties and behaviors of an object while hiding its implementation details. It is a form of abstraction in which we develop complicated data types and shield consumers from the specifics of their implementation. It allows for effective data management, enhances security, and shields internal representations from external entities.

This method has the advantage of resolving performance problems and gradually improving implementation. The code that is present on the client side is unaffected by any performance-related changes we make.

class BankAccount:

    def __init__(self, account_number, balance):
        self.account_number = account_number
        self.balance = balance
    def deposit(self, amount):
        self.balance += amount  # Corrected to update the balance
    def withdraw(self, amount):
        if amount <= self.balance:
            self.balance -= amount  # Corrected to update the balance
        else:
            print("Insufficient funds.")
    def display_balance(self):
        print("Account Number:", self.account_number)
        print("Balance:", self.balance)
# Example usage
account = BankAccount("1234567890", 5000)  # Corrected to use '=' instead of 'account'
account.deposit(2000)
account.withdraw(1000)
account.display_balance()

Output:

BankAccount class abstracts by encapsulating the account number and balance, hence the output.

2. Control Abstraction

Control abstraction is the process of identifying all identical and frequently repeated statements and making them appear as a single piece of workControl abstraction involves abstracting control flow mechanisms, such as loops and conditional statements, into higher-level constructs. 

This enhances code readability, simplifies complex logic, and promotes modularity.

Using functions in a program is the ideal example of control abstraction since it adheres to the fundamental principle of DRY programming, which stands for Don't Repeat Yourself.

def perform_calculations():
    total = 0
    while True:
        number = int(input("Enter a number (0 to stop): "))
        if number == 0:
            break
        total += number
    return total
# Example usage
result = perform_calculations()
print("Total:", result)

Output: 

The code abstracts the process of performing calculations on user input until the user enters 0, making the code more readable and simplifying the control flow logic.

Implementation of Abstraction

It is implemented as a class that merely depicts the crucial characteristics without providing background information. Including only the information that is necessary and keeping its internal implementation a secret. The Java implementation of abstraction is shown below: 

// Java program showing the working of abstraction
// Importing generic libraries
import java.io.*;
// Creating an abstract class
// demonstrate abstraction
abstract class Creature {
// Just providing that creatures has legs
// Hiding the number of legs
abstract void No_Of_legs();
}
// A new child class is extending
// the parent abstract class above
class Elephant extends Creature {

// Implementation of the abstract method
void No_Of_legs()
{
// Printing message of function in non abstract
// child class
System.out.println("It has four legs");
}
}
// Again a new child class is extended from parent
// Human class to override function created above
class Human extends Creature {
// Same function over-riden
public void No_Of_legs()
{
// Message printed if this function is called or
// Implementation of the abstract method
System.out.println("It has two legs");
}
}
public class TOTO {
// Main driver method
public static void main(String[] args)
{
// Creating human object showing the implementation
Human ob = new Human();
ob.No_Of_legs();
// Creating object of above class in main
Elephant ob1 = new Elephant();
// Calling the function in main by
// creating object of above non abstract class
ob1.No_Of_legs();
// Implementation of abstraction
}
}

Output:

This code demonstrates abstraction by defining an abstract class "Creature" with an abstract method "No_Of_legs()", which is then implemented in the concrete child classes "Elephant" and "Human" to provide the specific number of legs each creature has when called in the main driver method.

Advantages of Abstraction

Abstraction offers several benefits, including:

  • Code reusability

  • Modularity

  • Maintainability

  • Enhanced flexibility

It promotes efficient collaboration among developers, reduces code duplication, and allows for easier code maintenance and updates

What is Data Hiding?

Data hiding in OOPs is a principle that focuses on encapsulating data within a class, preventing direct access from external entities. It ensures that sensitive data remains hidden and can only be accessed through controlled mechanisms. It is not recommended that external individuals or groups have direct access to internal data. It is accomplished by utilizing a private modifier as an access specifier. 

Concept Involved in Data Hiding: Getter and Setter

To achieve data hiding, developers utilize getter and setter methods. Getters provide controlled access to retrieve the values of private data members, while setters allow for controlled modification of those values. This approach ensures data integrity and encapsulation.

After authentication, getter is used to access private data, while setter is used to change private data. It is essentially concealing internal information from users outside the company. No internal data will be accessible without authentication, thanks to its use as security. Internal data will not be accessible to an unauthorized end user. By designating data items as private, we can implement data hiding in programs.

We now have a unique method known as getter setter for modification, depending on the need, to access this data. After authentication, getter is used to access private data, while setter is used to change private data.

Data hiding example in java:

// Java Program showing working of data hiding
// Importing generic libraries
import java.io.*;
// Class created named Bank
class Bank {
// Private data (data hiding)
private long CurBalance = 0;
// Bank_id is checked for authentication
long bank_id;
String name;
// Getter function to modify private data
public long get_balance(long Id)
{
// Checking whether the user is
// authorized or unauthorized
// Comparing bank_id of user and the given Id
// then only it will get access
if (this.bank_id == Id) {
// Return current balance
return CurBalance;
}
// Unauthorized user
return -1;
}
// Setter function
public void set_balance(long balance, long Id)
{
// Comparing bank_id of user and the given Id
// then only it will get access
if (this.bank_id == Id) {
// Update balance in current ID
CurBalance = CurBalance + balance;
}
}
}
// Another class created- Employee
public class Emp {
public static void main(String[] args)
{
// Creating employee object of bank type
Bank _emp = new Bank();
// Assigning employee object values
_emp.bank_id = 12345;
_emp.name = "Roshan";
// _emp.get_balance(123456)
_emp.set_balance(10000, 12345);
// This will no get access as bank_id is given wrong
// so
// unauthorized user is not getting access that is
// data hiding
long emp_balance = _emp.get_balance(12345);
// As this time it is valid user it will get access
// Display commands
System.out.println("User Name"
+ " " + _emp.name);
System.out.println("Bank_ID"
+ " " + _emp.bank_id);
System.out.println("Current Balance"
+ " " + emp_balance);
}
}

Output:

This Java code demonstrates data hiding by defining a class "Bank" with a private data member "CurBalance" that can only be accessed or modified through the public getter and setter methods, ensuring that unauthorized users cannot directly access or modify the balance.

Key Differences Between Abstraction and Data Hiding

If you're wondering, "In what way is data hiding related to data abstraction?” – Data hiding and abstraction share the goal of enhancing code maintainability and security, but they differ in their focus and approach. Abstraction aims to simplify complex systems and create higher-level representations, while data hiding focuses on encapsulating and securing data within classes.

Conclusion

Understanding the differences between data hiding and abstraction is crucial for designing robust and maintainable software systems. Abstraction allows for modeling complex systems, while data hiding ensures the security and encapsulation of sensitive data. By leveraging these concepts effectively, developers can create modular, flexible, and secure codebases.

FAQs

1. What is the difference between data hiding and encapsulation?

Ans: The difference between data hiding and encapsulation is that data hiding is a concept of restricting access to certain data members, while encapsulation is a broader concept that encompasses data hiding and also includes bundling data and methods together within a class.

2. Data hiding is also known as?

Data hiding is also known as information hiding. This concept promotes the idea of data safety and security in software design by restricting direct access to certain data components.

3. How does a class enforce data hiding?

A class enforces data hiding by declaring certain data members as private, which means they can only be accessed or modified within the class itself. This prevents direct access to the data from outside the class and encourages the use of getter and setter methods to control access to the data.

Leave a Reply

Your email address will not be published. Required fields are marked *