AP CSA 3.1: Abstraction and Program Design

AP CSA • Unit 3: Class Creation • Lesson 3.1

AP CSA 3.1: Abstraction and Program Design

Before you type a class, decide what an object knows and what it does. Nouns become attributes, verbs become behaviors, and one question decides whether an attribute belongs to the object or to the whole class.

Design Code Develop Code Analyze Code Document Code Use Computers Responsibly
Loading the interactive lesson. If this note stays visible, this preview is blocking JavaScript. Download the file and open it in a browser (Chrome), or view it on the live page, to use the editor, game, and quiz.
Learn
Practice
Assess
The short answer

Abstraction means keeping what matters and discarding what does not. To design a class, read the specification, turn its nouns into attributes and its verbs into behaviors, then ask one question about each attribute: does every object need its own value? If yes it is an instance variable; if all objects share one value it is a class variable, marked static. Attributes are private unless the specification says otherwise. That is the whole of AP CSA 3.1, and it is the first two points of every Class Design free-response question.

Learn

What you will learn

  • Define abstraction, data abstraction, and procedural abstraction, and say what each one hides
  • Turn a written specification into a list of attributes and a list of behaviors
  • Choose between an instance variable and a class variable using the one design question
  • Explain why attributes are private, and what breaks when they are not
  • Reject an attribute that should be a computed behavior, and one that belongs to another class
  • Predict what a design produces before it is written, including shared-counter and aliasing cases

Why this matters on the exam

Under the 2025 CED, AP CSA is four units, and Unit 3: Class Creation is worth roughly a quarter of the multiple-choice section. Its real weight is larger than that number suggests, because free-response question 2 is Class Design every single year. You are handed a scenario and a table of calls and results, and you write the class from nothing: the header, the private instance variables, the constructor, and the methods.

Lesson 3.1 is where the points on that question are decided. Two of the four rubric points in a typical Class Design question go to the attributes and the constructor, and the single most common way to lose them is a design error rather than a syntax error: an attribute declared per object when the specification describes one shared value, a value stored that should have been computed, or a public field where the specification implies the class protects its own data. None of those produce a compiler message. They produce working code that is wrong, which is exactly what this lesson trains you to catch.

On the multiple-choice side, 3.1 shows up as design-judgment questions: which class design is best, which of I, II and III are appropriate instance variables, and what a program prints when a static counter is involved. Those questions are answerable in fifteen seconds if you have the one design question memorized, and are near-coin-flips if you do not.

Scenario

The problem this solves

A campus wants an app for its scooter fleet. Somebody has to decide, before any code exists, what a scooter is to the program. Its color and its serial number plate do not matter. Its battery level, whether it is currently rented, and the fleet's running count of scooters do. That decision, made on paper in about five minutes, is the difference between a class you can finish and one you rewrite twice. FRQ 2 on the exam hands you a scenario and a table of interactions and asks you to make exactly that decision, then implement it.

Skill focus: today you Design Code (choose the attributes and behaviors before typing anything), Analyze Code (predict what a given design produces), and Document Code (read and write the Javadoc and preconditions a class specification is made of).
Learn

Design first: turn a real thing into a class

Abstraction is reducing complexity by focusing on the main idea and hiding the details that do not matter for the question at hand. Designing a class is abstraction in two directions at once: you decide what an object knows and what an object does, and you throw away everything else.

The habit that pays off on FRQ 2 is simple. Read the specification, underline the nouns, underline the verbs. The nouns become attributes (the data). The verbs become behaviors (the methods). Do that on paper before you type a single line.

Nouns become attributes, verbs become behaviors

// Spec: a scooter has a battery level and
// can be rented, parked, and ridden.

public class Scooter {
    // attributes: what it KNOWS
    private int battery;
    private boolean rented;

    // behaviors: what it DOES
    public void rent() { ... }
    public void park() { ... }
    public void ride(int minutes) { ... }
}
The translation
noun attribute (data)
verb behavior (method)
adjective usually a boolean
"how many" usually an int
Data abstraction gives data a name without committing to how it is stored. Callers ask a Scooter for its battery level; they never need to know it is an int field named battery.

One per object, or one for the whole class?

An attribute is declared in the class, outside every method and constructor. There are two kinds, and choosing the wrong one is the single most common design mistake in this unit.

public class Ticket {
    // class variable: ONE copy, shared
    private static int issued = 0;

    // instance variable: one PER object
    private int number;

    public Ticket() {
        issued++;
        number = issued;
    }
}
Which kind?
instance variable one copy per object
class variable one copy, shared by all
keyword static marks a class variable
test "does each object need its own?"

Ask one question: does every object need its own value? Each ticket needs its own number, so that is an instance variable. The running count of how many tickets exist belongs to the whole class, so that is a class variable.

Watch out: if you drop the static from issued, every Ticket gets its own private counter that starts at 0. Each new ticket then reports number 1, and nothing about the code looks broken. The compiler will not warn you. Only tracing the design catches it.

Procedural abstraction: name it, decompose it, generalize it

A procedural abstraction gives a process a name so it can be used knowing only what it does, not how. Three moves follow from it.

  • Name it. isAvailable() says what it means; battery >= 20 && !rented makes the reader re-derive it every time.
  • Decompose it. Break a large behavior into smaller methods, each doing one job. Method decomposition is what turns a 40-line method into four readable ones.
  • Generalize it with a parameter. Three near-identical methods almost always want to be one method with a parameter.
// duplicated: three near-copies
public int priceWithTax5() { ... }
public int priceWithTax7() { ... }
public int priceWithTax9() { ... }

// generalized: one method, any rate
public int priceWithTax(int percent) {
    return subtotal + subtotal * percent / 100;
}
Why generalize
less code one place to fix a bug
reusable works for a rate you never listed
parameters are what make it general
The payoff: once a behavior has a name and a signature, you can rewrite its insides to be faster or shorter and never tell the callers, as long as the signature and what it does stay the same. That is why designing the outside first is worth the time.
Watch out: a behavior that changes the object should update the object's own attribute. Assigning to the parameter instead changes only a local copy, the object never changes, and the code compiles and runs quietly. This is the second most common design bug in the unit.

Vocabulary

Term Meaning
Abstraction Reducing complexity by focusing on the main idea and hiding details that do not matter for the question at hand.
Data abstraction Giving data a name without referencing how it is actually stored, so callers depend on the name and not the representation.
Attribute A data abstraction declared in a class outside every method and constructor. Attributes are either instance variables or class variables.
Instance variable An attribute whose value is unique to each object. Every object carries its own copy.
Class variable An attribute shared by all objects of the class. One copy exists, marked with the static keyword.
Behavior Something an object can do, implemented as a method. Behaviors come from the verbs in the specification.
Procedural abstraction Naming a process so it can be used knowing only what it does, not how it does it.
Method decomposition Breaking a large behavior into smaller methods, each responsible for one job.
Precondition What must already be true when a method is called for it to work as described. It is documented, not enforced.

Predict first, then check

1. ride runs battery -= minutes / 3;. A scooter starts at battery 40, then ride(7) and ride(5) are called. What is battery?
2. A class declares private static int made = 0; and its constructor runs made++. After three objects are created, what does made hold?
3. An attribute that every object of the class shares one single copy of is declared with which keyword? (one word)
Learn • error analysis

Common misconceptions

Each of these is a real answer students give. Read the wrong version first and decide why it is wrong before you read the fix.

Confusing an attribute with a behavior

Wrong"Adding a song is one of the things a Playlist has, so addSong belongs in the attribute list."
RightAttributes are the nouns a specification uses for data the object stores: a name, a count, a running time. Behaviors are the verbs: add, remove, shuffle. If the phrase describes something the object does, it becomes a method, never a variable. Underline nouns and verbs in two different colors before you write anything and this stops being a judgment call.

Making everything an instance variable

Wrong"Every object needs the count of how many objects exist, so each one stores its own count field."
RightAsk the design question: does every object need its own value? A running total of how many objects have been made is one fact about the whole class, so it is declared static and there is exactly one copy. Give each object its own copy instead and every object counts to 1 and stops. The program compiles, runs, and is silently wrong, which is why this is the defect the exam reaches for most often.

Making everything static to avoid the decision

Wrong"Adding static made the error go away, so I will put it on every field."
RightA static attribute is shared, so marking a per-object value static makes every object report the same thing. Two bank accounts would share one balance. The keyword is a design statement, not a repair tool: use it only when the specification says all objects share one value.

Storing a value that should be computed

Wrong"A Kiln should store the heating flag so it does not have to work it out every time."
RightIf a value can be derived from attributes the object already holds, derive it in a behavior. Storing it creates two facts that can disagree: change the temperature without updating the flag and the object confidently reports a stale answer. Store what is independent, compute what follows from it.

Leaving instance variables public

Wrong"The method checks for a negative value, so the count can never go negative."
RightA class can only enforce a rule if all access runs through its own code. A public field lets any caller write straight past the check. Declare attributes private unless the specification says otherwise: on the exam a public instance variable is almost always a distractor.
See it in memory

See the design in memory

Two Scooter objects and one shared class variable. Watch each object get its own copy of the instance variables while the class variable count is shared, then watch a second name point at an existing object.

Scooter a = new Scooter(50);
Scooter b = new Scooter(30);
a.ride(10);
Scooter c = b;
c.ride(9);
Stack (variables)
Heap (objects)
Design in memory: each Scooter object holds its own id and battery (instance variables), while a single made counter is shared by the whole class (class variable). Assigning c = b copies the reference, so b and c name one object and a change through c is visible through b. Open in a browser to step through the animation.
Original interactive memory model. Stack names hold arrows; heap boxes hold each object's own attributes; the class variable box is shared by every object.
Practice • write and run real Java

Live code editor

Eight problems, six scaffolded and two open-ended. Write Java and press Run to execute it. When you are ready, press Submit to test it against the expected output; the reference solution then appears underneath, next to your own code rather than on top of it. Hints are there if you are stuck, and attempts and hints are both tracked.

Problem 1 (Predict): Trace the designScaffolded
Trace the commented segment by hand. Do not uncomment it. Print the exact value it would print.
attempts: 0
Problem 2 (Predict): Boundary, short circuit, shared countScaffolded
Trace the commented segment by hand. It prints three lines. Print all three, in order.
attempts: 0
Problem 3 (Complete): One counter for the whole classScaffolded
Every Trip needs its own miles, but the count of trips belongs to the class. Fill in the two gaps.
attempts: 0
Problem 4 (Complete): Turn the sentence into the conditionScaffolded
The design says: a scooter is available when its battery is at least 20 AND it is not rented. Write that behavior.
attempts: 0
Problem 5 (Debug): Every ticket says number 1Scaffolded
The design calls for one shared sequence: ticket 1, ticket 2, ticket 3. It compiles and runs, but every ticket comes out as 1. Find the design defect and fix it.
attempts: 0
Problem 6 (Debug): The odometer never movesScaffolded
addTrip is supposed to add the trip distance to the odometer. It compiles, it runs, and the total never changes. Find the defect and fix it.
attempts: 0
Problem 7 (Write): Put each attribute at the right levelOpen-ended
The class is finished except for its three attributes. Decide which belong to each object and which belongs to the whole class, then declare them.

A Kiln fires pottery in a studio that has several of them. The class is finished except for its three attributes.

The three attributes

temperature
the current temperature of this kiln
target
the temperature this kiln is set to
firing
how many kilns in the whole studio are firing

The two forms you can choose between

private int example;
one copy per object
private static int shared = 0;
one copy for the whole class
The design question: does every kiln need its own value? Two of these do. The third is one fact about the studio.
attempts: 0
Problem 8 (Write): Store what is independent, compute the restOpen-ended
The balance is deliberately not an attribute, because it follows from two values the object already holds. Fill in the two behaviors that work it out.

A Ledger tracks money for one club. It stores what came in and what went out, and nothing else.

Attributes, already declared for you

deposits
total cents ever put into this ledger
spends
total cents ever taken out of this ledger

The two behaviors to fill in

int getBalance()
works the balance out from deposits and spends
boolean canSpend(int cents)
true when the balance covers that amount exactly or more
The balance is deliberately not stored. Storing it would create a second fact that can disagree with the first two. Watch the boundary: spending exactly the balance is allowed.
attempts: 0
Practice • fluency

Design Decisions Arcade

Six quick rounds. Read the class and the client code, then type the final value. These are the six design traps that show up again and again on FRQ 2: per-object versus shared, integer division, reference copying, and parameter copying.

Round 1 of 6. Final value of x?
public class S {
    private int b;
    public S(int start) { b = start; }
    public void ride(int m) { b -= m / 3; }
    public int get() { return b; }
}
S s = new S(60);
s.ride(11);
s.ride(7);
int x = s.get();
Round 2 of 6. Final value of x?
public class T {
    private static int n = 0;
    public T() { n++; }
    public static int get() { return n; }
}
T a = new T();
T b = new T();
T c = new T();
T d = new T();
int x = T.get();
Round 3 of 6. Final value of x?
public class T {
    private int n = 0;
    public T() { n++; }
    public int get() { return n; }
}
T a = new T();
T b = new T();
int x = b.get();
Round 4 of 6. Final value of x?
public class Box {
    private int v;
    public Box(int start) { v = start; }
    public void set(int n) { v = n; }
    public int get() { return v; }
}
Box p = new Box(4);
Box q = p;
q.set(12);
int x = p.get();
Round 5 of 6. Final value of x?
public class M {
    public static void bump(int n) { n += 100; }
}
int x = 5;
M.bump(x);
Round 6 of 6. Final value of x?
public class Meter {
    private int min;
    private int rate;
    public Meter(int r) { rate = r; min = 0; }
    public void insert(int c) { min += c / rate; }
    public int get() { return min; }
}
Meter m = new Meter(20);
m.insert(95);
m.insert(50);
int x = m.get();
Assess • twelve questions at AP difficulty

Multiple choice

Predict your answer before reading the options. Watch for the qualifier words. After you answer, the rationale explains every distractor.

Predict first
Predict the output before you read the options. What does this segment print?
public class Tank {
    private int gas;

    public Tank(int start) {
        gas = start;
    }

    public void drive(int miles) {
        gas -= miles / 4;
    }

    public int getGas() {
        return gas;
    }
}

Tank t = new Tank(30);
t.drive(9);
t.drive(7);
System.out.println(t.getGas());
Spot the design defect
The Ticket class is meant to hand out one shared sequence of numbers: 1, then 2, then 3. It compiles and runs, but every ticket reports number 1. Which single change fixes the design?
public class Ticket {
    private int issued = 0;
    private int number;

    public Ticket() {
        issued++;
        number = issued;
    }

    public int getNumber() {
        return number;
    }
}
Analyze: I, II, III
After the two objects below are created, which statements are true?
public class Locker {
    private static int built = 0;
    private int capacity;
    private int count;

    public Locker(int cap) {
        built++;
        capacity = cap;
        count = 0;
    }

    public static int getBuilt() { return built; }
    public int getCount() { return count; }
}

Locker a = new Locker(3);
Locker b = new Locker(5);

I.   a and b hold different values for capacity
II.  Locker.getBuilt() returns 2
III. a and b share one single count variable
NOT stem
A programmer is designing a Playlist class for a music app. Three of these belong in the design as attributes. Which one is NOT an attribute?
public class Playlist {
    // attributes go here
    // behaviors go below
}
Best answer
A Cart class has three nearly identical methods, priceWithTax5, priceWithTax7, and priceWithTax9, each returning the subtotal plus that percent of tax. Which redesign best applies procedural abstraction?
public class Cart {
    private int subtotal;

    public int priceWithTax5() { ... }
    public int priceWithTax7() { ... }
    public int priceWithTax9() { ... }
}
Spot the design defect
The Inventory class is meant to guarantee that count is never negative. The guarantee does not hold. Which statement identifies the defect?
public class Inventory {
    public int count;

    public Inventory(int start) {
        if (start < 0) {
            start = 0;
        }
        count = start;
    }

    public void remove(int n) {
        if (n <= count) {
            count -= n;
        }
    }
}
EXCEPT stem
A library is designing a LoanCopy class. The library charges the same late fee rate for every copy in the building. Each of the following is correctly declared as an instance variable EXCEPT which one?
public class LoanCopy {
    // one of these four is declared at the wrong level
}
Best answer
A Kiln must track a target temperature and a current temperature, and report whether it is heating, which is true exactly when current is below target. Which design is best?
public class Kiln {
    // attributes?

    // behaviors?
}
Best answer
A RaceClock stores elapsed time as a whole number of seconds and exposes getSeconds(). The team rewrites it to store tenths of a second internally, and getSeconds() still returns whole seconds. Which BEST explains why calling code does not change?
Analyze: I, II, III
A team is designing a Recipe class for a cooking app. Which of the following are appropriate INSTANCE variables for Recipe?
I.   servings, the number of portions this recipe makes
II.  totalCalories, found by adding up every ingredient
III. printedCopies, how many times any recipe in the
     app has ever been printed
Predict first
Predict the value before you read the options. What does this segment print?
public class Wristband {
    private static int made = 0;
    private int id;

    public Wristband() {
        id = made;
        made++;
    }

    public int getId() {
        return id;
    }
}

Wristband a = new Wristband();
Wristband b = new Wristband();
Wristband c = a;
Wristband d = new Wristband();
System.out.println(d.getId());
Predict first
What does this segment print?
public class Meter {
    private int minutes;
    private int rate;

    public Meter(int centsPerMinute) {
        rate = centsPerMinute;
        minutes = 0;
    }

    public void insert(int cents) {
        minutes += cents / rate;
    }

    public void tick(int n) {
        minutes -= n;
        if (minutes < 0) {
            minutes = 0;
        }
    }

    public int getMinutes() {
        return minutes;
    }
}

Meter m = new Meter(25);
Meter same = m;
m.insert(70);
same.insert(60);
same.tick(4);
System.out.println(m.getMinutes());
Assess • free-response connection

FRQ Practice

Free-response question 2 on the AP Exam is Class Design, and it is the one question that is Unit 3 from top to bottom. It hands you a scenario and a table showing how the class is used and what each call produces, and you build the class to match.

That question has two halves. The first is the design: which attributes exist, which level each one belongs at, and which values are computed rather than stored. The second is the syntax that expresses it, which arrives across 3.3 to 3.7. This is the design half, worth 4 points. Every header below is written for you; the decisions are not.

A gym issues a membership card to each member. A card counts that member's check-ins and knows the monthly fee that member pays. The gym also wants to know how many cards it has issued in total.

Call Result
new MemberCard(4000) a card at 4000 cents a month, 0 visits so far
costPerVisit() 4000 before any visit, because dividing by zero visits is not allowed
checkIn() three times, then costPerVisit() 4000 / 3 = 1333, whole cents only
isFrequent() false at 3 visits, true at exactly 10
MemberCard.getIssued() every card the gym has issued, not per member

Scoring: 1 point for placing the three attributes at the right level, 1 point for the constructor doing all three of its jobs, 1 point for isFrequent landing exactly on the boundary, and 1 point for costPerVisit using integer division and guarding the no-visits case.

FRQ Practice (4 points): finish the MemberCard designOpen-ended
Every header is given. Fill in the five decisions marked TODO. Two of the six test lines are edge cases: the cost before any visit, and the exact 10-visit boundary.

A gym issues a MemberCard to each member. A card counts that member's check-ins and knows the monthly fee they pay. The gym also wants to know how many cards it has issued in total.

Attributes to declare

visits
check-ins by this member
monthlyFee
cents this member pays each month
issued
cards the whole gym has issued

Behaviors, headers already written

MemberCard(int fee)
records the fee, starts visits at 0, and adds one to the gym's issued total
void checkIn()
records one visit for this member
boolean isFrequent()
true once this member reaches 10 visits
int costPerVisit()
the monthly fee divided by the visits so far, in whole cents
Two edge cases decide two of the four points. Before any visit there is nothing to divide by, so return the full fee. And 10 visits counts as frequent, not 11.
attempts: 0
Every student challenged

Choose your lane

Support

  • Reread the Code and Memory panels
  • Editor problems 1 to 3 with hints on
  • Retry the quiz until 80%
  • Use the FRQ method shell

Core

  • All 8 editor problems
  • Full game run
  • The 12-question quiz once
  • The FRQ connection

Challenge

  • Open-ended problems 7 and 8 with no hints
  • Rewrite one loop a different way
  • Extend the FRQ
  • Lead a class trace
Review

Summary

Designing a class is abstraction applied twice. You decide what an object knows, which becomes its attributes, and what an object does, which becomes its behaviors, and you discard everything the program has no use for. The mechanical version of that is to read the specification, underline the nouns and the verbs, and let the two lists become the two halves of the class.

Every attribute then faces one question: does every object need its own value? A per-object answer means an instance variable, one copy for every object. A shared answer means a class variable, declared static, with exactly one copy no matter how many objects exist. Getting this backwards is the defining error of the unit, and it never announces itself: a per-object counter compiles cleanly and reports 1 forever.

Two more rules finish the design. Store only what is independent, and compute anything that can be derived, so the object cannot hold two facts that disagree. And keep attributes private, because a class can only guarantee a rule when all access to its data runs through its own methods. Procedural abstraction is the same instinct applied to code: name a process, decompose a long behavior into small ones, and replace near-identical methods with one method that takes a parameter.

Key takeaways

  • Abstraction is deciding what to ignore. Design is choosing which details the class does not carry.
  • Nouns become attributes, verbs become behaviors. Do this on paper before typing.
  • One design question settles instance vs class: does every object need its own value?
  • static means one shared copy for the whole class, not "a fix for an error".
  • Store independent data; compute anything that follows from it, so nothing can go stale.
  • Attributes are private unless the specification says otherwise. Public fields break the guarantee.
  • A design bug compiles and runs. Tracing the design, not the compiler, is what catches it.
Review

Frequently asked questions

What is the difference between an instance variable and a class variable?

An instance variable gets one copy per object, so two objects can hold different values for it. A class variable is declared with static and there is exactly one copy shared by every object of the class, so changing it through one object changes it for all of them. The test is a single question: does every object need its own value? Each bank account needs its own balance, so balance is an instance variable. The number of accounts the bank has opened is one fact about the whole class, so it is static.

Why should instance variables be private?

Because a class can only enforce a rule when every path to its data goes through its own code. If a field is public, a caller can assign whatever it likes and the validation inside the methods never runs. Making it private and exposing behaviors instead is encapsulation, and it is also what lets you change how a value is stored later without breaking any calling code. On the AP exam, treat a public instance variable as a red flag unless the specification explicitly asks for one.

How much of the AP CSA exam is Unit 3?

Under the 2025 CED four-unit structure, Unit 3: Class Creation is about a quarter of the multiple-choice section, and it is the entirety of free-response question 2, which is a Class Design task every year. That question hands you a scenario and a table of calls, and you write the class from scratch. Lesson 3.1 is where its first two rubric points, the attributes and the constructor, are won or lost.

How do I decide what belongs in a class and what does not?

Ask what the program needs to do. An attribute earns its place if it is data this object owns, it cannot be computed from the other attributes, and it varies from object to object. That rules out three common mistakes at once: details that belong to a different class, values that should be derived in a method, and app-wide totals that should be static. Anything left over is the abstraction you keep.

What is the difference between data abstraction and procedural abstraction?

Data abstraction hides how a value is stored. Callers use getSeconds(), so the class is free to store tenths of a second internally without any calling code changing. Procedural abstraction hides how a process works. Callers use isAvailable() and never see the condition behind it, so that condition can be rewritten freely. Both trade a hidden detail for a stable name, which is what makes a program possible to change later.

Do I need to know UML diagrams for the AP CSA exam?

No. The AP CSA exam does not require you to read or draw UML. Class diagrams are a useful way to sketch attributes and behaviors while you plan, and some textbooks lean on them, but the exam gives you a written specification and a table of calls with their results. Practice reading that format instead, because that is the one free-response question 2 will hand you.

0 / 32 points
Editor 0/10 • Game 0/6 • Quiz 0/12 • FRQ 0/4

Get in Touch

Whether you're a student, parent, or teacher — I'd love to hear from you.

Just want free AP CS resources?

Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.

Typically responds within 24 hours

Message Sent!

Thanks for reaching out. I'll get back to you within 24 hours.

🏫 Welcome, fellow educator!

I offer curriculum resources, practice materials, and study guides designed for AP CS teachers. Let me know what you're looking for — whether it's classroom materials, a guest speaker, or Teachers Pay Teachers resources.

Email

[email protected]

📚

Courses

AP CSA, CSP, & Cybersecurity

Response Time

Within 24 hours

Prefer email? Reach me directly at [email protected]