2022 AP® Computer Science A FRQ 2 — Textbook (Inheritance and Subclasses)

Topic: Class inheritance and subclass design

Skills Tested: Creating subclasses, super keyword, constructor chaining, method overriding, equals() comparison

Curriculum Alignment: Unit 5 (Writing Classes), Unit 9 (Inheritance)

Question

The Book class is used to store information about a book. A partial Book class definition is shown.

Provided Book Class

public class Book {
    /** The title of the book */
    private String title;
    
    /** The price of the book */
    private double price;
    
    /** Creates a new Book with given title and price */
    public Book(String bookTitle, double bookPrice) {
        /* implementation not shown */
    }
    
    /** Returns the title of the book */
    public String getTitle() {
        return title;
    }
    
    /** Returns a string containing the title and price of the Book */
    public String getBookInfo() {
        return title + "-" + price;
    }
    
    // There may be instance variables, constructors, and methods 
    // that are not shown.
}

Your Task

Write a class Textbook, which is a subclass of Book.

A Textbook has an edition number, which is a positive integer used to identify different versions of the book.

The getBookInfo method, when called on a Textbook, returns a string that also includes the edition information.

Requirements

  • Information about the book title and price must be maintained in the Book class.
  • Information about the edition must be maintained in the Textbook class.
  • The Textbook class must have a canSubstituteFor method that returns true if a Textbook is a valid substitute for another Textbook.
  • A Textbook is a valid substitute if:
    • The two Textbook objects have the same title, AND
    • The edition of the current Textbook is greater than or equal to the edition of the parameter.

Examples

Statement Value Returned Explanation
Textbook bio2015 = new Textbook("Biology", 49.75, 2); (object created) bio2015 has title "Biology", price 49.75, edition 2
Textbook bio2019 = new Textbook("Biology", 39.75, 3); (object created) bio2019 has title "Biology", price 39.75, edition 3
bio2019.getEdition(); 3 The edition is returned
bio2019.getBookInfo(); "Biology-39.75-3" Formatted string with title, price, and edition
bio2019.canSubstituteFor(bio2015); true Same title, and edition 3 ≥ edition 2
bio2015.canSubstituteFor(bio2019); false Same title, but edition 2 < edition 3
Textbook math = new Textbook("Calculus", 45.25, 1); (object created) math has title "Calculus", price 45.25, edition 1
bio2015.canSubstituteFor(math); false Different titles ("Biology" ≠ "Calculus")

Solution & Explanation

Complete Textbook Class

public class Textbook extends Book {
    private int edition;
    
    // Constructor
    public Textbook(String title, double price, int ed) {
        super(title, price);
        edition = ed;
    }
    
    // Accessor for edition
    public int getEdition() {
        return edition;
    }
    
    // Override getBookInfo to include edition
    @Override
    public String getBookInfo() {
        return super.getBookInfo() + "-" + edition;
    }
    
    // Check if this textbook can substitute for another
    public boolean canSubstituteFor(Textbook other) {
        return this.getTitle().equals(other.getTitle()) 
            && this.edition >= other.edition;
    }
}

Step-by-Step Explanation

1. Class Declaration

public class Textbook extends Book
  • Uses extends keyword to create inheritance relationship
  • Textbook IS-A Book (can do everything a Book can do, plus more)
  • Inherits all public/protected methods and fields from Book

2. Private Instance Variable

private int edition;
  • Stores the edition number for this textbook
  • Must be private (encapsulation best practice)
  • Maintained in Textbook class, not Book class (as required)

3. Constructor with super()

public Textbook(String title, double price, int ed) {
    super(title, price);
    edition = ed;
}
  • Takes 3 parameters: title, price, ed
  • super(title, price) MUST be first line
  • Calls Book's constructor to initialize inherited fields (title, price)
  • Cannot access title and price directly (they're private in Book)
  • Then initializes the edition field
⚠️ Critical Point: The super() call MUST be the first statement in the constructor. Without it, the Book fields won't be properly initialized.

4. getEdition() Accessor Method

public int getEdition() {
    return edition;
}
  • Standard accessor (getter) method
  • Returns the edition number
  • Required because edition is private

5. Override getBookInfo()

@Override
public String getBookInfo() {
    return super.getBookInfo() + "-" + edition;
}
  • @Override annotation indicates this method overrides a parent method
  • super.getBookInfo() calls Book's version to get "title-price"
  • Concatenates "-" + edition to add edition number
  • Returns format: "title-price-edition"
  • Must use super.getBookInfo() because we can't access private fields directly

6. canSubstituteFor() Method

public boolean canSubstituteFor(Textbook other) {
    return this.getTitle().equals(other.getTitle()) 
        && this.edition >= other.edition;
}
  • Takes another Textbook as parameter
  • Compares titles using equals() method (NOT ==)
  • Uses getTitle() because title is private in Book
  • Compares edition numbers using >= operator
  • Both conditions must be true (uses &&)
  • Returns true only if same title AND this edition ≥ other edition
⚠️ Common Error: Students often use == instead of equals() for String comparison. The == operator checks if two variables reference the same object, not if they have the same content.

Detailed Explanation

Key Concepts Tested

1. Inheritance Fundamentals

This FRQ tests your understanding of the IS-A relationship. A Textbook IS-A Book with additional features. This means:

  • Textbook inherits all public methods from Book
  • Textbook can call Book's methods using super
  • Textbook can override Book's methods to customize behavior
  • Textbook cannot directly access Book's private fields

2. The super Keyword

The super keyword has two important uses in this problem:

  • super(params) - Calls the parent class constructor
  • super.method() - Calls the parent class method

You cannot use super.field because fields are typically private in the parent class.

3. Method Overriding

When you override getBookInfo() in Textbook:

  • The method signature must match exactly
  • You can use @Override annotation (recommended)
  • You can call the parent version with super.getBookInfo()
  • This is called extending the parent method's behavior

4. String Comparison with equals()

For the canSubstituteFor method, you must use equals() to compare Strings:

// ✅ CORRECT
this.getTitle().equals(other.getTitle())

// ❌ WRONG - compares memory addresses, not content
this.getTitle() == other.getTitle()

Why This Design?

The problem is designed to test whether you understand the proper relationship between classes:

  • Book maintains general book information (title, price)
  • Textbook adds specific information (edition)
  • Title and price belong in Book because all books have these
  • Edition belongs in Textbook because only textbooks have editions

Constructor Chaining

The constructor demonstrates constructor chaining:

public Textbook(String title, double price, int ed) {
    super(title, price);  // Chain to Book constructor
    edition = ed;         // Initialize Textbook-specific field
}

This ensures that Book's fields are properly initialized before Textbook adds its own initialization.

Common Mistakes to Avoid

Constructor Errors

  • Not calling super(): Forgetting super(title, price) in constructor
  • Wrong super() placement: Calling super() after initializing edition (must be first)
  • Wrong parameters: Calling super(title, price, ed) (Book constructor only takes 2 parameters)

Field Access Errors

  • Direct field access: Trying to use this.title or this.price (they're private in Book)
  • Using super.title: Trying super.title (still can't access private fields)
  • Correct approach: Use getTitle() method or super.getBookInfo()

Method Override Errors

  • Not using super: Rewriting all the Book logic instead of calling super.getBookInfo()
  • Wrong return format: Returning "title-edition" instead of "title-price-edition"
  • Wrong method signature: Changing parameters or return type (breaks override)

canSubstituteFor Errors

  • Using == for Strings: this.getTitle() == other.getTitle() (checks references, not content)
  • Wrong comparison operator: Using > instead of >= for edition
  • Wrong boolean logic: Using || instead of &&
  • Direct field access: Using other.title instead of other.getTitle()

Declaration Errors

  • Wrong visibility: Making edition public instead of private
  • Missing accessor: Not providing getEdition() method
  • Wrong class declaration: Not using extends Book
💡 Practice Tip: Try writing this solution without looking at the answer. Focus on: (1) Using super() correctly in constructor, (2) Calling super.getBookInfo() in override, (3) Using equals() for String comparison. Time yourself for 20 minutes.

Scoring Rubric

Total: 9 Points

Point Criteria
1 Class header declares Textbook extends Book
1 Declares private int edition instance variable
1 Constructor header with correct parameters (String, double, int)
1 Calls super(title, price) to initialize Book fields
1 Initializes edition field in constructor
1 getEdition() method returns edition
1 getBookInfo() calls super.getBookInfo() and includes edition
1 canSubstituteFor() compares titles using equals()
1 canSubstituteFor() correctly compares editions with >= and returns boolean

Penalty Deductions (Max 3)

  • -1: Array/collection access confusion
  • -1: Extraneous code that causes side effects
  • -1: Local variables used but not declared
  • -1: Destruction of persistent data
  • -1: Void method returns a value

📄 Official College Board Resources

Written by Tanner, Certified AP Computer Science Teacher with 5+ years teaching AP CSA.

Last updated:

Contact form