MultPractice: 2017 FRQ 2
A step-by-step solution to the 2017 AP CSA FRQ 2 (MultPractice), covering designing a class that implements an interface and produces a sequence of formatted practice problems in Java.
Designing a class from nothing but an interface and a couple of worked examples is the whole task in this AP Computer Science A free-response question — no class skeleton is handed to you at all, only the contract it has to satisfy.
What This FRQ Tests
- AP CSA units: Unit 5 (Writing Classes) and Unit 9 (Interfaces)
- Core skill: implementing an interface with
implements, matching its method signatures exactly - Secondary skill: modeling a small amount of state (two
ints) that changes across repeated method calls - Official category: "Classes" — this lines up with the modern fixed FRQ 2 slot, though that fixed FRQ 1–4 ordering itself wasn't standardized until the 2019–2020 Course and Exam Description redesign; 2017's actual printed order was Digits, MultPractice, Phrase, Successors.
The Setup
- The given
StudyPracticeinterface requires exactly two methods:String getProblem()— returns the current practice problemvoid nextProblem()— advances to the next practice problem
- No class skeleton is provided for
MultPractice— you design the entire class yourself. - A
MultPracticeobject is built from two integers: a first integer that stays constant forever, and an initial second integer that increases by one every timenextProblem()is called. getProblem()must return aStringformatted exactly as"first TIMES second".
Building the MultPractice Class
Step-by-Step Approach
- Decide what state needs to persist: one
intthat never changes (the first number) and oneintthat increments over time (the second number). - Write a constructor that takes both integers and stores them directly in those two fields.
- Write
getProblem()to build and return aStringfrom the current values of both fields, joined by" TIMES ". - Write
nextProblem()to increment only the second field. - Declare the class header as
public class MultPractice implements StudyPractice— this is what makes it legal to store aMultPracticein aStudyPractice-typed variable, exactly as both examples in the question do.
The Code
public class MultPractice implements StudyPractice
{
private int firstNum;
private int secondNum;
public MultPractice(int first, int second)
{
firstNum = first;
secondNum = second;
}
public String getProblem()
{
return firstNum + " TIMES " + secondNum;
}
public void nextProblem()
{
secondNum++;
}
}
Why Each Piece Matters
implements StudyPractice— without it,StudyPractice p1 = new MultPractice(7, 3);wouldn't compile, since aMultPracticecouldn't be treated as aStudyPractice.firstNumis never reassigned anywhere outside the constructor — this is what "remains constant" actually means in code: the field is set once and simply never touched again.secondNum++is the only thingnextProblem()does — it's the single piece of state that changes over the object's lifetime.getProblem()rebuilds the string from the current field values every call — it doesn't cache a value computed once at construction, so it always reflects whatevernextProblem()calls have happened so far.
Tracing the Example
Example 1 — StudyPractice p1 = new MultPractice(7, 3);:
| Call | firstNum |
secondNum |
Output |
|---|---|---|---|
p1.getProblem() |
7 | 3 | 7 TIMES 3 |
p1.nextProblem() then p1.getProblem() |
7 | 4 | 7 TIMES 4 |
p1.nextProblem() then p1.getProblem() |
7 | 5 | 7 TIMES 5 |
p1.nextProblem() then p1.getProblem() |
7 | 6 | 7 TIMES 6 |
Example 2 — StudyPractice p2 = new MultPractice(4, 12);:
| Calls | secondNum |
Output |
|---|---|---|
p2.nextProblem(); then p2.getProblem() |
13 | 4 TIMES 13 |
p2.getProblem() again, no nextProblem() in between |
13 (unchanged) | 4 TIMES 13 |
p2.nextProblem(); p2.nextProblem(); then p2.getProblem() |
15 | 4 TIMES 15 |
p2.nextProblem(); then p2.getProblem() |
16 | 4 TIMES 16 |
The repeated "4 TIMES 13" in Example 2 is the important detail: calling getProblem() twice in a row with no nextProblem() call between them returns the identical string both times, since getProblem() never changes any state on its own — matching the question's output exactly.
Common Mistakes to Avoid
- Forgetting
implements StudyPracticein the class header. Both examples declare their variable as typeStudyPractice, so without it, the code that constructs aMultPracticethis way wouldn't compile. - Incrementing the wrong field in
nextProblem()— incrementingfirstNum(or resettingsecondNum) instead of incrementingsecondNumbreaks the "first stays constant" rule. - Getting the spacing or capitalization of
" TIMES "wrong. The exact expected format is"first TIMES second"— a single space on each side of the all-caps word. - Expecting
getProblem()to advance state. OnlynextProblem()changes anything; callinggetProblem()any number of times in a row without callingnextProblem()must return the same string every time.
Key Takeaways
- Implementing an interface means matching every one of its required methods with an identical signature — that's what makes an object usable wherever the interface type is expected.
- When no class skeleton is given, work backward from the constructor's parameters and the example call sequences to figure out exactly which fields are actually needed.
- A method whose job is only to report state (like
getProblem()) should never accidentally change it — only the method whose entire purpose is advancing state (nextProblem()) should modify a field.