Information Hiding
Overview
The principle of Information Hiding emphasizes concealing the internal details of a module, class, or component, and exposing only what is necessary through well-defined interfaces. By hiding implementation details, systems reduce coupling, improve maintainability, and increase security. This principle underlies encapsulation in object-oriented programming and is fundamental to designing robust Java applications.
Learning Objectives
- Understand the principle of Information Hiding and its role in software design.
- Learn how it differs from and complements Encapsulation.
- Apply Information Hiding in Java using access modifiers, interfaces, and abstractions.
- Use real-world examples and UML to demonstrate its impact.
- Prepare for interview questions about encapsulation, modularity, and API design.
Why It Matters
If internal details are exposed unnecessarily, client code becomes tightly coupled to the implementation. This makes systems fragile and hard to change. Information Hiding ensures that only a minimal, stable API is visible, while internal details remain private and subject to change without breaking clients.
Benefits:
- Reduced Coupling: Clients depend only on contracts, not implementations.
- Maintainability: Internal changes do not break external code.
- Security: Sensitive details remain inaccessible to unauthorized code.
- Flexibility: Implementation can evolve without impacting clients.
Key Concepts
Encapsulation vs Information Hiding:
- Encapsulation is bundling data and methods together.
- Information Hiding is restricting visibility of internal details.
- Together, they ensure modular, maintainable designs.
Access Modifiers in Java:
private
: Hide details within a class.protected
: Limited exposure to subclasses.public
: Expose necessary APIs.package-private
(default): Visible only within the package.
APIs vs Implementation: Public APIs should be stable, while private implementation details can change freely.
Relation to Design Principles: Supports SRP, OCP, and DIP by keeping dependencies abstract and minimal.
Code Example: Bank Account
Without Information Hiding
// Exposes internal state directly
public class BankAccount {
public double balance; // bad practice
public BankAccount(double balance) {
this.balance = balance;
}
}
public class Client {
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
// Directly manipulates balance
account.balance = -500;
System.out.println("Balance: " + account.balance);
}
}
- Problems: Internal state is public, allowing invalid operations. Breaks encapsulation and security.
With Information Hiding
// Internal details hidden, exposed via controlled API
public class BankAccount {
private double balance; // hidden
public BankAccount(double balance) {
if (balance < 0) throw new IllegalArgumentException("Initial balance cannot be negative");
this.balance = balance;
}
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Deposit must be positive");
balance += amount;
}
public void withdraw(double amount) {
if (amount <= 0 || amount > balance) throw new IllegalArgumentException("Invalid withdrawal amount");
balance -= amount;
}
}
- Solution: Balance is private. Access and modifications happen only through controlled methods.
- Result: Client code depends only on stable APIs, not internal representation.
UML (After)
+---------------------+
| BankAccount |
+---------------------+
| -balance: double |
+---------------------+
| +getBalance(): double |
| +deposit(amount): void |
| +withdraw(amount): void|
+---------------------+
Real-World Applications
- Banking Systems: Hide account balances and transactions behind APIs.
- Libraries & Frameworks: Expose stable APIs, hide implementation behind private methods or internal classes.
- Security Systems: Prevent direct access to sensitive data.
- Microservices: Hide internal services and expose only APIs at the service boundary.
Practice Exercises
- Easy: Create a
User
class that hides password storage, exposing onlysetPassword
andvalidatePassword
methods. - Medium: Refactor a
Car
class to hide engine details, exposing only high-level operations likestart
,accelerate
. - Medium: Build a
Library
system where books are managed internally, and only APIs likeborrowBook
andreturnBook
are exposed. - Hard: Design a
PaymentGateway
class where sensitive keys are hidden, exposing only transaction-related methods.
Interview Insights
- “What is the difference between Encapsulation and Information Hiding?”
- “Why should fields usually be private in Java?”
- “What are the risks of exposing internal state?”
- “How does Information Hiding relate to modularity?”
Conclusion
Information Hiding protects system integrity by exposing only what’s necessary and concealing internal details. By applying this principle, you design Java systems that are modular, maintainable, and secure. Combined with encapsulation and other design principles, it forms the foundation of robust software engineering.
Next Step: Explore Principle of Least Privilege to learn how to further secure your systems by limiting access rights.