Object Oreinted Programming
Object Oreinted Programming
3. HYBRID APPROACH:
- Core Components: Use OOP to design the main classes for data modeling,
encapsulation, and easy addition of new features.
- Modules for Functional Organization: Divide the application into modules by
functionality. For instance:
- `UserModule` for handling user-related actions (signup, profile management).
Page | 1
- `MessageModule` for messaging logic, which could use polymorphism for
message types.
- `NotificationModule` for handling real-time notifications and updating users.
- Scalable Architecture: With modules, each component can be scaled
independently based on demand. This is essential for supporting millions of users.
Question 2:
ISSUES IN THE INITIAL DESIGN
1. Code Duplication: Common functions (e.g., borrowing and reserving) are
repeated in multiple subclasses.
2. Inflexibility: Adding new media types requires modifying existing classes,
making the codebase prone to errors.
3. Complexity: A deep inheritance hierarchy leads to a hard-to-maintain and
complex structure.
CODE:
interface Borrowable {
void borrow();
void returnItem();
Page | 2
double calculateLateFee(int daysLate);
}
interface Reservable {
void reserve();
void cancelReservation();
}
CODE:
abstract class MediaItem {
private String title;
private String author;
private String catalogNumber;
Page | 3
- Create separate classes for functionalities instead of coding them directly in the
media subclasses. For instance, create a `BorrowingService` to handle the
borrowing logic, late fees, and reservations.
CODE:
class BorrowingService {
public void borrowItem(MediaItem item) {
// Logic for borrowing an item
}
CODE:
class MediaItemFactory {
public static MediaItem createMediaItem(String type, String title, String author)
{
switch (type) {
case "Book": return new Book(title, author);
case "EBook": return new EBook(title, author);
// Other cases for media types
default: throw new IllegalArgumentException("Invalid media type");
}
}
}
Page | 4
5. Apply the Open-Closed Principle for Future Expansion:
- By decoupling functionality (borrowing, reserving) from the `MediaItem`
subclasses, you can add new behaviors or media types without modifying existing
code. This follows the Open-Closed Principle, which ensures the system is open to
extension but closed to modification.
CODE:
interface LateFeeStrategy {
double calculateFee(int daysLate);
}
BENEFITS OF REDESIGN:
1. Improved Reusability: Interfaces (`Borrowable`, `Reservable`) allow reusing
functionality across different media types without duplicating code.
Page | 5
2. Enhanced Maintainability: Separating logic into distinct services (e.g.,
`BorrowingService`) simplifies the codebase and isolates responsibilities, making
the code easier to understand and maintain.
3. Greater Extensibility: Using the Factory and Strategy patterns allows you to
introduce new media types or behaviors without modifying existing code, following
the Open-Closed Principle.
Question 3:
CODE:
class BankAccount {
// Fields
private String accountNumber;
private double balance;
// Constructor
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
Page | 6
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrew: $" + amount);
} else {
System.out.println("Insufficient funds or invalid withdrawal amount.");
}
}
// Deposit $500
account.deposit(500);
// Withdraw $200
account.withdraw(200);
Page | 7
}
Question 4:
CODE:
class Rectangle {
// Fields
private double length;
private double width;
// Constructor
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
Page | 8
Rectangle rectangle = new Rectangle(5, 3);
Question 5:
CODE:
import java.util.ArrayList;
class Student {
// Fields
private String name;
private String studentID;
private ArrayList<Double> grades;
// Constructor
public Student(String name, String studentID) {
this.name = name;
this.studentID = studentID;
this.grades = new ArrayList<>();
}
Page | 9
grades.add(grade);
}
Page | 10
alice.addGrade(78.0);
Question 6:
CODE:
class Car {
// Fields
private String make;
private String model;
private double fuelLevel;
private double fuelConsumption; // in liters per kilometer
// Constructor
public Car(String make, String model, double fuelLevel, double fuelConsumption)
{
this.make = make;
this.model = model;
this.fuelLevel = fuelLevel;
this.fuelConsumption = fuelConsumption;
}
Page | 11
if (fuelNeeded <= fuelLevel) {
fuelLevel -= fuelNeeded;
System.out.println("Drove " + distance + " km. Fuel used: " + fuelNeeded +
" liters.");
} else {
System.out.println("Not enough fuel to drive " + distance + " km.");
}
}
Page | 12
Car car = new Car("Toyota", "Corolla", 50, 0.05);
Question 7:
CODE:
class LibraryBook {
// Fields
private String title;
private String author;
private boolean isCheckedOut;
// Constructor
public LibraryBook(String title, String author) {
this.title = title;
this.author = author;
this.isCheckedOut = false; // Book is available by default
}
Page | 13
public void checkOut() {
isCheckedOut = true;
System.out.println(title + " has been checked out.");
}
Page | 14
// Print the book's status again
System.out.println("Status: " + book.getStatus());
}
}
Question 8:
CODE:
class Person {
// Fields
private String name;
private int age;
private String address;
// Default constructor
public Person() {
this.name = "Unknown";
this.age = 0;
this.address = "Not specified";
}
Page | 15
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
// Create an instance using the constructor that accepts name and age
Person person2 = new Person("Alice", 30);
person2.displayInfo();
// Create an instance using the constructor that accepts name, age, and
address
Page | 16
Person person3 = new Person("Bob", 25, "123 Main St");
person3.displayInfo();
}
}
Question 9:
CODE:
class Book {
// Fields
private String title;
private String author;
private int yearPublished;
private String ISBN;
Page | 17
// Overloaded constructor that accepts all fields
public Book(String title, String author, int yearPublished, String ISBN) {
this.title = title;
this.author = author;
this.yearPublished = yearPublished;
this.ISBN = ISBN;
}
// Create an instance using the constructor that accepts title, author, and
yearPublished
Book book2 = new Book("1984", "George Orwell", 1949);
Page | 18
book2.displayDetails();
Question 10:
CODE:
class Product {
// Fields
private String productID;
private String name;
private double price;
// Constructor
public Product(String productID, String name, double price) {
this.productID = productID;
this.name = name;
this.price = price;
}
Page | 19
System.out.println("Price: $" + price);
}
Page | 20
productA.displayProductInfo();
System.out.println("\nDetails of productC:");
productC.displayProductInfo();
}
}
Question 11:
CODE:
class DataProcessor {
// Fields
private int processorID;
private int[] data;
// Constructor
public DataProcessor(int processorID, int[] data) {
this.processorID = processorID;
this.data = data;
System.out.println("DataProcessor with ID " + processorID + " created.");
}
Page | 21
// Override finalize method to display message on garbage collection
@Override
protected void finalize() {
System.out.println("DataProcessor with ID " + processorID + " is being garbage
collected.");
}
}
Question 12:
Step 1: First of all, define the `BankAccount` Class with
Encapsulation and Access Control
Page | 22
1. Encapsulation with Private Fields:
- Make the fields `accountNumber`, `balance`, and `accountHolderName` private.
This prevents direct access to these fields from outside the class, enforcing
encapsulation.
CODE:
package banking;
// Constructor
public BankAccount(String accountNumber, double initialBalance, String
accountHolderName) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
Page | 23
this.accountHolderName = accountHolderName;
}
// Deposit method
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
} else {
System.out.println("Invalid deposit amount.");
}
}
// Withdraw method
public void withdraw(double amount) {
Page | 24
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrew: " + amount);
} else {
System.out.println("Insufficient funds or invalid amount.");
}
}
}
CODE:
package banking;
CODE:
Page | 25
package external;
import banking.BankAccount;
Question 13:
Code Implementation
`Character` Class:
CODE:
// Character.java in package rpg
package rpg;
Page | 26
// Constructor
public Character(String name, int health, int level) {
this.name = name;
this.health = health;
this.level = level;
}
`Warrior` Class:
CODE:
// Warrior.java in package rpg
package rpg;
Page | 27
// Implement abstract attack method
public void attack() {
System.out.println("Warrior attacks with a sword!");
}
`Mage` Class:
CODE:
// Mage.java in package rpg
package rpg;
Page | 28
// Cast spell method
public void castSpell() {
level += 1; // Accessing protected level field
System.out.println("Mage casts a spell and increases level to " + level);
}
}
// Create a Mage
Mage mage = new Mage("Merlin", 80, 1);
mage.displayStatus();
mage.attack();
mage.castSpell();
mage.displayStatus();
}
Page | 29
}
Question 14:
Code Implementation
// File: mathlib/basic/Calculator.java
package mathlib.basic;
Page | 30
}
}
// File: mathlib/advanced/Statistics.java
package mathlib.advanced;
import java.util.Arrays;
// Public Statistics Class…..
public class Statistics {
// Calculates the mean of a data set
public double mean(double[] data) {
double sum = 0;
for (double num : data) {
sum += num;
}
return sum / data.length;
}
Page | 31
public double standardDeviation(double[] data) {
double mean = mean(data);
double sum = 0;
for (double num : data) {
sum += (num - mean) * (num - mean);
}
return Helper.sqrt(sum / data.length); // Using package-private Helper method
}
}
// File: mathlib/advanced/Helper.java
package mathlib.advanced;
Page | 32
System.out.println("Addition: " + calc.add(5, 3));
System.out.println("Division: " + calc.divide(10, 2));
Question 15:
COMPLEX NUMBER CLASS DEVELOPMENT
CODE:
package midlab;
class ComplexNumber {
double real;
double imaginary;
Page | 33
}
System.out.print("num1: ");
num1.display();
System.out.print("num2: ");
num2.display();
System.out.print("sum: ");
sum.display();
System.out.print("difference: ");
difference.display();
}
}
Question 16:
STUDENT CLASS DEVELOPMENT
CODE:
import java.util.ArrayList;
class Student {
Page | 34
String name;
String studentID;
ArrayList<Double> grades;
Page | 35
Question 17:
COUNTER CLASS DEVELOPMENT:
CODE
class Counter {
private int id;
private static int count = 0;
public Counter() {
count++;
this.id = count;
}
Question 18:
CODE:
class MathUtility {
public static int factorial(int n) {
if (n < 0) throw new IllegalArgumentException("n must be non-negative.");
Page | 36
int result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
Page | 37
int gcdValue = MathUtility.gcd(48, 18);
Question 19:
CODE:
public class TestScores {
public static void main(String[] args) {
int[] scores = {85, 92, 76, 81, 95};
int sum = 0;
int highest = scores[0];
int lowest = scores[0];
Page | 38
System.out.println("Average Score: " + average);
System.out.println("Highest Score: " + highest);
System.out.println("Lowest Score: " + lowest);
}
}
Question 20:
CODE:
public class TheaterSeating {
public static void main(String[] args) {
int[][] seats = new int[3][4]; // 0 for available, 1 for booked
Page | 39
}
}
Question 21:
CODE:
public class AverageCalculator {
public static void main(String[] args) {
double[] numbers = {10.5, 23.8, 5.7, 17.6, 9.0};
double average = calculateAverage(numbers);
System.out.println("Average: " + average);
}
Question 22:
CODE:
import java.util.Arrays;
Page | 40
// Sort the array
Arrays.sort(numbers);
System.out.println("Sorted array: " + Arrays.toString(numbers));
Question 23:
CODE:
import java.util.Arrays;
Page | 41
// Modify the first element of each copied array
clonedArray[0] = 99;
copiedArray[0] = 99;
Question 24:
CODE:
public class StringImmutabilityExample {
public static void main(String[] args) {
String original = "Hello";
String modified = original + " World";
Question 25:
CODE:
public class Point {
private final double x;
private final double y;
Page | 42
public Point(double x, double y) {
this.x = x;
this.y = y;
}
Page | 43
QUESTION 26:
CODE:
// Mutable counter class
class CounterMutable {
private int count;
Page | 44
return count;
}
}
Question 27:
CODE:
public class Main {
Page | 45
public static void main(String[] args) {
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
Question 28:
CODE:
import java.util.Date;
Page | 46
}
Question 29:
BENEFITS OF USING IMMUTABLE CLASSES
Thread Safety: Immutable classes cannot change, making them safe to use in
multi-threaded programs without synchronization issues.
Page | 47
Easier Debugging: Their unchanging nature simplifies understanding and tracking
down problems in the code.
Better Performance with Reuse: They can be reused safely, saving memory and
improving performance by avoiding unnecessary object creation.
Potential Drawbacks of Using Immutable Classes
More Memory Use: Creating new instances for every change can consume more
memory compared to modifying existing objects.
Slower Updates: The need to create new objects for updates can lead to slower
performance in data-intensive applications.
When to Use Immutable Classes
Safe Data Sharing: Use them when sharing data between parts of a program to
prevent accidental changes.
Simple Data Transfer: They are ideal for transferring data where you want to
ensure the original data remains unchanged.
When Not to Use Immutable Classes
Frequent Changes: If your application requires frequent data updates, mutable
objects might be more efficient.
Complex Structures: In cases with complex data structures that need constant
modification, mutable objects can be easier to manage.
Page | 48