ApexSensei

Drills Classes & objects

Static versus instance members

Classes & objects · Intermediate · 16 min · Runs in your Salesforce Developer org · Free

Finish a `Counter` class with two fields: a `static Integer total` shared across every instance, and an `Integer myCount` that belongs to one Counter. The `bump()` method must raise both by one. The `label()` method must read them back as `total:<total> mine:<myCount>`.

Lesson

Why this matters

Some values belong to a single object. Each Counter has its own myCount. Other values belong to the class itself, so every instance sees the same number. If you forget which is which, two Counters can clobber each other, or a running total resets every time you make a new one. The keyword that decides this is static.

The smallest working example

public class Counter {
    public static Integer total = 0; // shared by every Counter
    public Integer myCount = 0;      // one per Counter

    public void bump() {
        total++;
        myCount++;
    }

    public String label() {
        return 'total:' + total + ' mine:' + myCount;
    }
}

Name the parts

  • **static Integer total** lives on the class. There is one copy for the whole transaction, and you reach it as Counter.total.
  • **Integer myCount** lives on each object. Two Counters have two separate counts.
  • Inside the class you can write just total or myCount; outside, use Counter.total for the static.
  • The static resets at the start of each transaction, not between method calls.

A common wrong version

public class Counter {
    public Integer total = 0;        // not static
    public static Integer myCount = 0; // static by mistake
}

total is now per-instance, so every new Counter starts its own "shared" total at 0. myCount is on the class, so every Counter overwrites the same number. Both tests about "shared total" and "separate counts" fail together.

The fix

Put static on the field you want to share, and leave it off the one you do not:

public static Integer total = 0;
public Integer myCount = 0;

Now you try

Fill in the fields and the two methods. Keep the class name and the method names; the hidden tests reset Counter.total to zero before each test.

Learn more

The challenge

Finish Counter so a shared static total and a per-instance myCount both update when bump() is called.

Examples:

  • a.bump() sets a.myCount to 1 and Counter.total to 1
  • a later b.bump() leaves a.myCount at 1 but raises Counter.total to 2
  • label() reads total:<class static> mine:<my count>

Requirements:

  1. firstCounterBumpsBoth should pass: one Counter bumped once reads total:1 mine:1.
  2. secondCounterSharesTotal should pass: a second Counter raises the shared total but keeps its own count.
  3. totalReadableFromClassName should pass: Counter.total is reachable through the class name.
  4. instancesHaveDistinctCounts should pass: each Counter keeps its own myCount.

Starter code

public class AS_51395E17F340_Counter {
    public void bump() {
    }

    public String label() {
        return '';
    }
}

Related drills

Try this drill free

You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.

‹ finally and several catch blocks · Extend an abstract score rule ›