FRQ
› csapa
Book / Textbook: 2022 FRQ 2
A step-by-step solution to the 2022 AP CSA FRQ 2 (Textbook), covering inheritance, super() constructors, and method overriding in Java.
Writing a subclass that extends a given parent class is at the heart of this AP Computer Science A free-response question — you add a new field and new behavior on top of what the parent class already provides, without ever touching its private data directly.
What This FRQ Tests
- AP CSA units: Unit 9 (Inheritance) and Unit 5 (Writing Classes)
- Core skill: extending a class with
extends, calling the parent's constructor withsuper(...), and overriding a method so it extends rather than replaces the parent behavior - Secondary skill: respecting
privateaccess — a subclass cannot read or write a parent's private fields directly, even though it inherits them - Official category: "Classes" — always FRQ 2 on the AP CSA exam
The Setup
- The given
Bookclass has:private String titleandprivate double price— both inaccessible directly from any subclass- A constructor:
Book(String bookTitle, double bookPrice) String getTitle()— a public getter for the titleString getBookInfo()— returns"title-price"as a formattedString
- You're asked to write a new class,
Textbook, that:- Extends
Book - Adds one new field: a positive
int editionnumber - Overrides
getBookInfo()so it also includes the edition, formatted as"title-price-edition" - Adds a new method:
canSubstituteFor(Textbook other)
- Extends
- The substitution rule: the current
Textbookcan substitute forotherif both are true:- The two
Textbookobjects have the same title - The current object's edition is greater than or equal to
other's edition
- The two
Building the Textbook Class
Step-by-Step Approach
- Declare the class as
public class Textbook extends Book— this is what makes it a subclass. - Add exactly one new instance field:
private int edition. (titleandpricealready exist — they live inBook, andTextbookinherits access to them through public methods, not directly.) - Write a constructor that takes all three pieces of data (title, price, edition), forwards title and price to
Book's constructor withsuper(...), and setseditionitself. - Add a simple getter,
getEdition(), since nothing else exposes the edition yet. - Override
getBookInfo(): call the parent version withsuper.getBookInfo()to get"title-price", then append"-" + edition. - Write
canSubstituteFor(Textbook other): compare titles with.equals(), compare editions with>=, and combine both with&&.
The Code
public class Textbook extends Book
{
private int edition;
public Textbook(String bookTitle, double bookPrice, int bookEdition)
{
super(bookTitle, bookPrice);
edition = bookEdition;
}
public int getEdition()
{
return edition;
}
public String getBookInfo()
{
return super.getBookInfo() + "-" + edition;
}
public boolean canSubstituteFor(Textbook other)
{
return getTitle().equals(other.getTitle()) && edition >= other.getEdition();
}
}
Why Each Piece Matters
super(bookTitle, bookPrice)— this is the only way to initializetitleandprice. They'reprivateinBook, soTextbookcannot assign them directly (title = bookTitle;insideTextbookwould not even compile).super.getBookInfo()— reusesBook's existing formatting logic instead of retypingtitle + "-" + price. IfBookever changed its formatting,Textbookwould automatically follow along.getTitle().equals(other.getTitle())— always compareStringcontents with.equals(), never==. Two differentStringobjects can hold the same characters;==would (incorrectly) compare whether they're the same object in memory.edition >= other.getEdition()— note the direction: "greater than or equal to," not just "greater than." ATextbookcan always substitute for an earlier or identical edition of itself.
Tracing the Example
Given from the question:
bio2015: title"Biology", price49.75, edition2bio2019: title"Biology", price39.75, edition3math: title"Calculus", price45.25, edition1
Trace through each call:
bio2019.getBookInfo()→super.getBookInfo()returns"Biology-39.75", then+ "-3"→"Biology-39.75-3"bio2019.canSubstituteFor(bio2015)→ titles match ("Biology"=="Biology"), and3 >= 2istrue→truebio2015.canSubstituteFor(bio2019)→ titles match, but2 >= 3isfalse→falsebio2015.canSubstituteFor(math)→ titles don't match ("Biology"vs."Calculus") → short-circuits tofalseimmediately, edition is never even checked
All four results match the table given in the question.
Common Mistakes to Avoid
- Trying to access
titleorpricedirectly (e.g.,title = bookTitle;insideTextbook's constructor). These fields areprivatetoBook— this simply won't compile. - Forgetting
super(...)entirely, which either fails to compile (ifBookhas no no-argument constructor) or leavestitle/priceuninitialized. - Rewriting the
"title-price"formatting instead of callingsuper.getBookInfo(). It works, but duplicates logic that already exists — reusing the parent's method is both simpler and safer against future changes. - Using
>instead of>=incanSubstituteFor. The rule specifically allows an equal edition to substitute for itself. - Comparing titles with
==instead of.equals(). This is one of the most common AP CSA point losses across every FRQ that touchesStringcomparison.
Key Takeaways
- A subclass never accesses a parent's
privatefields directly — it goes through the parent's constructor (super(...)) and public methods instead. - Overriding a method to extend behavior (rather than fully replace it) almost always means calling
super.methodName()first, then adding to the result. Stringcomparisons always use.equals(), never==.