Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Mastering Inheritance in Java: Build a Book Management System Like a Pro

Learn Java inheritance by building a bookstore and library book system. This step-by-step tutorial covers abstract classes, constructors, toString, and polymorphism with real-world examples from school projects.

Java inheritance tutorial COP3330 homework 3 abstract class Java example book management system Java polymorphism Java array toString override Java BookstoreBook LibraryBook Java OOP project for students Java programming assignment help inheritance in Java with example Java constructor chaining instanceof operator Java school library system Java Java coding exercise COP3330 trending Java OOP concepts 2026

Why Inheritance Matters in Java (And Your COP3330 Homework)

Inheritance is a cornerstone of object-oriented programming (OOP) that lets you reuse code and model real-world relationships. In your COP3330 homework 3, you're asked to create BookstoreBook and LibraryBook classes that share common fields like author, title, and isbn. Instead of writing duplicate code, you'll use an abstract class Book to hold the shared logic. Think of it like a gaming leaderboard: all players have a name and score (common fields), but some are online players (extra stats) and others are AI bots (different behavior). Inheritance lets you define the base player once and extend it.

Setting Up the Abstract Book Class

An abstract class cannot be instantiated directly—it's meant to be a blueprint. Here, Book will hold author, title, isbn, plus getters, setters, and constructors. This is where you put the shared code.

public abstract class Book {
    private String author;
    private String title;
    private String isbn;

    // Constructors
    public Book() {}
    public Book(String author, String title, String isbn) {
        this.author = author;
        this.title = title;
        this.isbn = isbn;
    }

    // Getters and setters
    public String getAuthor() { return author; }
    public void setAuthor(String author) { this.author = author; }
    // ... similar for title and isbn

    @Override
    public String toString() {
        return isbn + "-" + title.toUpperCase() + " by " + author.toUpperCase();
    }
}

Notice the toString() method—overriding it gives you control over how the book is displayed. In the sample run, the output format is exactly [isbn-TITLE by AUTHOR].

Creating BookstoreBook with Sale Logic

The BookstoreBook class extends Book and adds price (double), onSale (boolean), and discountPercent (double). When a book is on sale, the discounted price is calculated. This is like a flash sale on an e-commerce app—you apply a percentage off.

public class BookstoreBook extends Book {
    private double price;
    private boolean onSale;
    private double discountPercent;

    // Constructors
    public BookstoreBook() { super(); }
    public BookstoreBook(String author, String title, String isbn, double price) {
        super(author, title, isbn);
        this.price = price;
        this.onSale = false;
        this.discountPercent = 0;
    }
    // Additional constructor with sale info

    public double getDiscountedPrice() {
        if (onSale) {
            return price * (1 - discountPercent / 100);
        }
        return price;
    }

    @Override
    public String toString() {
        String base = super.toString();
        if (onSale) {
            double discounted = getDiscountedPrice();
            return String.format("[%s, $%.2f listed for $%.2f]", base, price, discounted);
        } else {
            return String.format("[%s, $%.2f]", base, price);
        }
    }
}

The toString() uses super.toString() to reuse the base formatting and then appends the price info. This is a clean way to extend behavior without copying code.

LibraryBook with Auto-Generated Call Number

For LibraryBook, you add a callNumber field that is automatically generated from the author and isbn. According to the homework, the call number format is something like XX.AAA.X where the first part is the last two digits of the isbn, the middle is the first three letters of the author's last name (uppercase), and the last digit is the last digit of the isbn. This mimics how libraries shelve books—like a real-world Dewey Decimal system.

public class LibraryBook extends Book {
    private String callNumber;

    // Constructors
    public LibraryBook() { super(); }
    public LibraryBook(String author, String title, String isbn) {
        super(author, title, isbn);
        this.callNumber = generateCallNumber(author, isbn);
    }

    private String generateCallNumber(String author, String isbn) {
        // Extract last two digits of isbn
        String lastTwo = isbn.length() >= 2 ? isbn.substring(isbn.length()-2) : "00";
        // Extract first three letters of author's last name (assume last word)
        String[] parts = author.split(" ");
        String lastName = parts[parts.length-1].toUpperCase();
        String firstThree = lastName.length() >= 3 ? lastName.substring(0,3) : String.format("%-3s", lastName).replace(' ', 'X');
        // Last digit of isbn
        char lastDigit = isbn.charAt(isbn.length()-1);
        return lastTwo + "." + firstThree + "." + lastDigit;
    }

    @Override
    public String toString() {
        return super.toString() + "-" + callNumber;
    }
}

This demonstrates encapsulation—the call number generation is hidden inside the class. In the sample run, you see call numbers like 09.ERI.0.

Managing Books with BookList and Polymorphism

The homework requires a BookList class that holds an array of Book references (size 100). Because BookstoreBook and LibraryBook are subclasses of Book, you can store both types in the same array—this is polymorphism. At runtime, the correct toString() method is called based on the actual object type.

public class BookList {
    private Book[] list;
    private int count;

    public BookList() {
        list = new Book[100];
        count = 0;
    }

    public void addBook(Book b) {
        if (count < 100) {
            list[count++] = b;
        }
    }

    public void displayAll() {
        // Separate library and bookstore books
        System.out.println("Library Books (" + getLibraryCount() + ")");
        for (int i = 0; i < count; i++) {
            if (list[i] instanceof LibraryBook) {
                System.out.println(list[i]);
            }
        }
        System.out.println("Bookstore Books (" + getBookstoreCount() + ")");
        for (int i = 0; i < count; i++) {
            if (list[i] instanceof BookstoreBook) {
                System.out.println(list[i]);
            }
        }
    }

    private int getLibraryCount() {
        int c = 0;
        for (int i = 0; i < count; i++) {
            if (list[i] instanceof LibraryBook) c++;
        }
        return c;
    }

    private int getBookstoreCount() {
        int c = 0;
        for (int i = 0; i < count; i++) {
            if (list[i] instanceof BookstoreBook) c++;
        }
        return c;
    }
}

Notice the use of instanceof to check the actual type. This is essential when you need to treat objects differently based on their subclass.

Putting It All Together: The Main Class

The Main class handles user interaction. It prompts the user to create books, validates input (including case-insensitive yes/no, BB/LB), and stores them in the BookList. The sample run shows robust input handling—like accepting yEs and rejecting yeah.

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        BookList bookList = new BookList();
        String response;

        System.out.println("Welcome to the book program!");
        do {
            System.out.print("Would you like to create a book object? (yes/no): ");
            response = scanner.nextLine().trim().toLowerCase();
            if (response.equals("yes")) {
                // Get author, title, isbn
                System.out.print("Please enter the author, title and the isbn of the book separated by /: ");
                String[] parts = scanner.nextLine().split("/");
                String author = parts[0].trim();
                String title = parts[1].trim();
                String isbn = parts[2].trim();

                // Ask for type
                String type;
                while (true) {
                    System.out.print("Got it! Now, tell me if it is a bookstore book or a library book (enter BB for bookstore book or LB for library book): ");
                    type = scanner.nextLine().trim().toUpperCase();
                    if (type.equals("BB") || type.equals("LB")) break;
                    System.out.println("Oops! That's not a valid entry. Please try again.");
                }

                if (type.equals("BB")) {
                    System.out.print("Please enter the list price of " + title.toUpperCase() + " by " + author.toUpperCase() + ": ");
                    double price = Double.parseDouble(scanner.nextLine());
                    System.out.print("Is it on sale? (y/n): ");
                    boolean onSale = scanner.nextLine().trim().equalsIgnoreCase("y");
                    double discount = 0;
                    if (onSale) {
                        System.out.print("Deduction percentage: ");
                        discount = Double.parseDouble(scanner.nextLine().replace("%", ""));
                    }
                    BookstoreBook bb = new BookstoreBook(author, title, isbn, price);
                    bb.setOnSale(onSale);
                    bb.setDiscountPercent(discount);
                    bookList.addBook(bb);
                    System.out.println("Got it!\nHere is your bookstore book information " + bb);
                } else {
                    LibraryBook lb = new LibraryBook(author, title, isbn);
                    bookList.addBook(lb);
                    System.out.println("Got it!\nHere is your library book information " + lb);
                }
            } else if (!response.equals("no")) {
                System.out.println("I'm sorry but " + response + " isn't a valid answer. Please enter either yes or no.");
            }
        } while (!response.equals("no"));

        System.out.println("Sure!\nHere are all your books...");
        bookList.displayAll();
        System.out.println("Take care now!");
        scanner.close();
    }
}

Why This Matters Beyond Homework

Understanding inheritance and polymorphism is crucial for building scalable applications. For example, in a school library management system, you might have different types of media (books, DVDs, e-books) that all share a common base class. In AI apps, you could have a base Model class with subclasses like ImageModel and TextModel. Even in finance, you might have a base Account class with CheckingAccount and SavingsAccount subclasses. The pattern is everywhere.

By completing this assignment, you'll have a solid grasp of:

  • Abstract classes and why you can't instantiate them directly
  • Constructor chaining with super()
  • Overriding toString() for meaningful output
  • Using instanceof for type checking
  • Polymorphism to store different objects in one array

Remember to test edge cases: empty inputs, invalid numbers, and boundary conditions. Good luck with your COP3330 homework!