Object-Oriented Programming (OOP) is a programming paradigm centered around the concept of objects, which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods).
OOP is essential for several reasons:
- It helps organize complex code through the use of classes and objects.
- Facilitates code reusability through inheritance.
- Enables the implementation of real-world entities in programming.
- Improves code maintenance and flexibility.
Basic Concepts of OOP
1. Encapsulation
Encapsulation is the mechanism of bundling the data (attributes) and code acting on the data (methods) together as a single unit. It also restricts access to some of the object’s components, which is why encapsulation is also known as data hiding.
Why it’s needed: Encapsulation helps to protect the internal state of an object from unwanted external modification and bundles the data with methods that operate on that data.
2. Inheritance
Inheritance is a mechanism where a new class is derived from an existing class. The new class is called a subclass, and the existing class is called a superclass. Inheritance represents the IS-A relationship.
Why it’s needed: It promotes code reusability, allows for the logical grouping of classes, and enables polymorphism.
3. Polymorphism
Polymorphism allows objects of different classes to be treated as objects of a common super class. The most common use of polymorphism in OOP occurs when a parent class reference is used to refer to a child class object.
Why it’s needed: It enables one interface to be used for a general class of actions, which helps in reducing complexity by allowing the same interface to be used for different underlying forms (data types).
4. Abstraction
Abstraction is the concept of hiding the complex reality while exposing only the necessary parts. It’s about making complex systems simple by hiding the unnecessary details from the user.
Why it’s needed: It reduces complexity and allows the programmer to focus on interactions at a higher level.
Basic Concepts of OOP Illustrated with a Library Management System
Encapsulation: Book
Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class Book { private String title; private String author; // Constructor public Book(String title, String author) { this.title = title; this.author = author; } // Getter for title public String getTitle() { return title; } // Setter for title public void setTitle(String title) { this.title = title; } // Getter for author public String getAuthor() { return author; } // Setter for author public void setAuthor(String author) { this.author = author; } // Method to display information about the book public void displayInfo() { System.out.println("Book: " + getTitle() + " by " + getAuthor()); } } |
Encapsulation is demonstrated here by keeping title
and author
private and accessible only through a constructor and a public method. Using getters and setters not only ensures that the internal state of these objects is protected and accessible only through these methods but also allows for the possibility of validation and preprocessing before setting a value.
Inheritance: Extending Book
Class
AudioBook
Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class AudioBook extends Book { private int durationMinutes; // Constructor public AudioBook(String title, String author, int durationMinutes) { super(title, author); this.durationMinutes = durationMinutes; } // Getter for durationMinutes public int getDurationMinutes() { return durationMinutes; } // Setter for durationMinutes public void setDurationMinutes(int durationMinutes) { this.durationMinutes = durationMinutes; } // Overridden method to display information about the AudioBook @Override public void displayInfo() { super.displayInfo(); System.out.println("Format: AudioBook, Duration: " + getDurationMinutes() + " minutes"); } } |
EBook.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public class EBook extends Book { private int fileSizeMB; // Constructor public EBook(String title, String author, int fileSizeMB) { super(title, author); this.fileSizeMB = fileSizeMB; } // Getter for fileSizeMB public int getFileSizeMB() { return fileSizeMB; } // Setter for fileSizeMB public void setFileSizeMB(int fileSizeMB) { this.fileSizeMB = fileSizeMB; } // Overridden method to display information about the eBook @Override public void displayInfo() { super.displayInfo(); System.out.println("Format: EBook, File Size: " + getFileSizeMB() + "MB"); } } |
Inheritance allows EBook
to inherit from Book
and extend its functionality.
Polymorphism: Method Overriding
The displayInfo
method in EBook
and potentially other subclasses (like AudioBook
) can override the displayInfo
method in Book
, providing specific implementations. This is polymorphism in action, where the same method behaves differently based on the object that invokes it.
Abstraction
While the original examples did not explicitly include an abstract class or interface to demonstrate abstraction, let’s conceptualize how it might be applied:
An AbstractBook
class or Readable
interface could declare a method like displayInfo()
without providing an implementation. Subclasses would then provide their specific implementations. This way, abstraction hides the complex details behind a simpler interface.
The provided code snippets for Book
, EBook
, and potentially AudioBook
classes illustrate encapsulation (protecting the state of an object), inheritance (creating a new class from an existing class), and polymorphism (methods behaving differently based on the object type). Abstraction could further enhance this model by defining a common interface or abstract class for books, ensuring even greater flexibility and decoupling.
Demonstrating the use of all book types
To demonstrate the use of all book types (Book
, EBook
, and AudioBook
) in a unified context, let’s create a LibraryDemo
class. This class will instantiate objects of each book type and showcase how each behaves according to its specific implementation, while still adhering to the principles of OOP (Object-Oriented Programming).
The LibraryDemo
Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class LibraryDemo { public static void main(String[] args) { // Create instances of each book type Book regularBook = new Book("To Kill a Mockingbird", "Harper Lee"); EBook eBook = new EBook("1984", "George Orwell", 500); AudioBook audioBook = new AudioBook("The War of the Worlds", "H.G. Wells", 360); // Display information about each book regularBook.displayInfo(); eBook.displayInfo(); audioBook.displayInfo(); // Demonstrate the use of setters to update properties System.out.println("\nUpdating eBook and AudioBook properties...\n"); eBook.setFileSizeMB(550); // Update eBook file size audioBook.setDurationMinutes(365); // Update AudioBook duration // Display updated information eBook.displayInfo(); // Displays updated eBook info audioBook.displayInfo(); // Displays updated AudioBook info } } |
Expected Output and Explanation
1 2 3 4 5 6 7 8 9 10 11 12 |
Book: To Kill a Mockingbird by Harper Lee Book: 1984 by George Orwell Format: EBook, File Size: 500MB Book: The War of the Worlds by H.G. Wells Format: AudioBook, Duration: 360 minutes Updating eBook and AudioBook properties... Book: 1984 by George Orwell Format: EBook, File Size: 550MB Book: The War of the Worlds by H.G. Wells Format: AudioBook, Duration: 365 minutes |
In this demonstration:
- We first instantiate and display information for a regular
Book
, anEBook
, and anAudioBook
. Each book type utilizes thedisplayInfo
method to present details relevant to its type, illustrating polymorphism—the same method behaves differently depending on the object. - After initial display, we update the
EBook
file size and theAudioBook
duration using setters, showcasing encapsulation—internal state changes through public methods ensure data integrity and encapsulation. - The
EBook
andAudioBook
classes inherit from theBook
class, reusing its properties anddisplayInfo
method. They also override thedisplayInfo
method to add additional details specific to each type, further demonstrating polymorphism.
This example solidly illustrates the practical application of encapsulation, inheritance, and polymorphism—the core principles of OOP—in a Java program.