Question 1: POJOs

Situation: The school librarian aims to digitize the library’s inventory. Eager to contribute, you decide to apply your coding skills to create a program for managing the library’s book collection.

a. Access Modifiers in POJOs: Private access modifiers restrict access to within the class itself, ensuring data encapsulation and integrity by preventing external modifications. Public access modifiers, conversely, allow data to be accessed and modified from any class, increasing flexibility but potentially compromising data security. In POJOs, using private fields with public getters and setters balances data protection with accessibility.

b. Private vs. Public Scenario: In a banking application, an account’s balance should be private to prevent unauthorized modifications, ensuring only controlled access through public methods for deposits and withdrawals. This maintains the integrity of the account’s financial data.

c. Creating a Book Class: The following Java class represents a book, incorporating private fields for encapsulation and public getters and setters for controlled access:

import java.util.Date;

public class Book {
    // Private fields
    private String title;
    private String author;
    private Date datePublished;
    private String personHoldingBook;

    // Constructor
    public Book(String title, String author, Date datePublished, String personHoldingBook) {
        this.title = title;
        this.author = author;
        this.datePublished = datePublished;
        this.personHoldingBook = personHoldingBook;
    }

    // Getters and setters
    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getDatePublished() {
        return datePublished;
    }

    public void setDatePublished(Date datePublished) {
        this.datePublished = datePublished;
    }

    public String getPersonHoldingBook() {
        return personHoldingBook;
    }

    public void setPersonHoldingBook(String personHoldingBook) {
        this.personHoldingBook = personHoldingBook;
    }

    // toString method 
    @Override
    public String toString() {
        return "Book{" +
                "title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", datePublished=" + datePublished +
                ", personHoldingBook='" + personHoldingBook + '\'' +
                '}';
    }
}

Question 2: Writing Classes

(a) Class Components: A class in Java is a blueprint for creating objects. Key components include variables to store data, constructors for initialization, methods for behaviors, access modifiers for data protection, and getters/setters for accessing private fields.

(b) BankAccount Class: A simple representation of a bank account in Java demonstrating encapsulation and methods for managing account balance:

public class BankAccount {
    // Attributes
    private String accountHolder;
    private double balance;

    // Constructor
    public BankAccount(String accountHolder, double initialBalance) {
        this.accountHolder = accountHolder;
        this.balance = initialBalance;
    }

    
    public void setAccountHolder(String name) {
        this.accountHolder = name;
    }

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println(amount + " deposited successfully.");
        } else {
            System.out.println("Invalid deposit amount. Amount must be positive.");
        }
    }

    public void withdraw(double amount) {
        if (amount > 0) {
            if (amount <= balance) {
                balance -= amount;
                System.out.println(amount + " withdrawn successfully.");
            } else {
                System.out.println("Insufficient funds. Withdrawal amount exceeds balance.");
            }
        } else {
            System.out.println("Invalid withdrawal amount. Amount must be positive.");
        }
    }

    // cant withdraw more than exists
    private void ensureNonNegativeBalance() {
        if (balance < 0) {
            balance = 0;
        }
    }

    // Getters
    public String getAccountHolder() {
        return accountHolder;
    }

    public double getBalance() {
        return balance;
    }

    // testing purposes lol
    public static void main(String[] args) {
        // Create a bank account
        BankAccount account = new BankAccount("John Doe", 1000.0);

        // Display initial balance
        System.out.println("Initial balance: $" + account.getBalance());

        // Deposit $500
        account.deposit(500.0);

        // Withdraw $200
        account.withdraw(200.0);

        // Withdraw $2000 (exceeding balance)
        account.withdraw(2000.0);

        // Display final balance
        System.out.println("Final balance: $" + account.getBalance());
    }
}


BankAccount.main(null);
Initial balance: $1000.0
500.0 deposited successfully.
200.0 withdrawn successfully.
Insufficient funds. Withdrawal amount exceeds balance.
Final balance: $1300.0

Question 5: Inheritance

Situation: Developing a zoo management program, you utilize inheritance to model the hierarchy between different animal types, simplifying code through shared attributes and methods.

(a) Inheritance in Java: Inheritance allows a class (subclass) to inherit attributes and methods from another class (superclass), facilitating code reuse and extension. For instance, a general “Animal” class could be extended by specific animal classes like “Dog,” inheriting common attributes while adding specific ones.

(b) Implementing Animal Hierarchy: A superclass Animal is extended by subclasses like Mammal, Bird, and Reptile, each adding unique attributes and behaviors. This structure demonstrates inheritance’s power to streamline code structure in a zoo management context.

// Superclass representing all animals
class Animal {
    // private instance variables
    private String name;
    private int age;

    // constructors
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Method to display generic information about an animal
    public void displayInfo() {
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

// extending animal class with mammal subclass
class Mammal extends Animal {
    // Additional attribute for mammals
    private String furColor;

    // Constructor
    public Mammal(String name, int age, String furColor) {
        super(name, age); // Call superclass constructor
        this.furColor = furColor;
    }

    // Method to display specific information about mammals
    public void displayMammalInfo() {
        displayInfo(); // Call superclass method
        System.out.println("Fur Color: " + furColor);
    }
}

// Subclass representing birds
class Bird extends Animal {
    // Additional attribute for birds
    private boolean canFly;

    // Constructor
    public Bird(String name, int age, boolean canFly) {
        super(name, age); // Call superclass constructor
        this.canFly = canFly;
    }

    // Method to display specific information about birds
    public void displayBirdInfo() {
        displayInfo(); // Call superclass method
        System.out.println("Can Fly: " + canFly);
    }
}

// Subclass representing reptiles
class Reptile extends Animal {
    // Additional attribute for reptiles
    private boolean isColdBlooded;

    // Constructor
    public Reptile(String name, int age, boolean isColdBlooded) {
        super(name, age); // Call superclass constructor
        this.isColdBlooded = isColdBlooded;
    }

    // repitle information
    public void displayReptileInfo() {
        displayInfo(); // superclass method
        System.out.println("Is Cold-Blooded: " + isColdBlooded);
    }
}

// Main class for testing
public class Zoo {
    public static void main(String[] args) {
        // different animals
        Mammal lion = new Mammal("Lion", 5, "Golden");
        Bird eagle = new Bird("Eagle", 3, true);
        Reptile snake = new Reptile("Snake", 2, true);

        // printing info
        System.out.println("Mammal Information:");
        lion.displayMammalInfo();
        System.out.println();

        System.out.println("Bird Information:");
        eagle.displayBirdInfo();
        System.out.println();

        System.out.println("Reptile Information:");
        snake.displayReptileInfo();
    }
}


Zoo.main(null);
Mammal Information:
Name: Lion
Age: 5
Fur Color: Golden

Bird Information:
Name: Eagle
Age: 3
Can Fly: true

Reptile Information:
Name: Snake
Age: 2
Is Cold-Blooded: true

Through these examples, we’ve explored key concepts like POJOs, access modifiers, class composition, and inheritance, demonstrating their practical applications in software development without altering the provided code examples.