ApexSensei

Drills Classes & objects

Extend an abstract score rule

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

The provided `ScoreRule` is `abstract`: it already builds the `score:` label, but it refuses to say how many points an amount is worth. Finish `FlatScore` so it extends `ScoreRule` and overrides `pointsFor`. Return the amount for 0 or more, and return 0 when the amount is null or negative.

Lesson

Why this matters

Sometimes you want to share most of a class but leave one decision open. An abstract class is exactly that: it writes the shared code once (the score: label, logging, defaults) and declares the "you fill this in" methods with no body. Every subclass has to supply those bodies, which keeps the contract honest.

The smallest working example

public abstract class ScoreRule {
    public abstract Integer pointsFor(Integer amount);

    public String label(Integer amount) {
        return 'score:' + pointsFor(amount);
    }
}

public class FlatScore extends ScoreRule {
    public override Integer pointsFor(Integer amount) {
        if (amount == null || amount < 0) {
            return 0;
        }
        return amount;
    }
}

new FlatScore().label(10) returns score:10 because the shared label calls the subclass's pointsFor.

Name the parts

  • **abstract on the class** means you cannot write new ScoreRule(). You must build a subclass.
  • **abstract on a method** means no body, just a signature; a subclass must override it.
  • **extends** on the subclass links it to the abstract base so it can override and reuse the shared label.
  • null < 0 is false, not an exception. Test amount == null as well, or a null amount is returned unchanged.

A common wrong version

public class FlatScore extends ScoreRule {
    public override Integer pointsFor(Integer amount) {
        if (amount < 0) {
            return 0;
        }
        return amount;
    }
}

For pointsFor(null), null < 0 is false. It does not throw. With only that test, the method falls through and returns null. Test amount == null as well so a null amount returns 0.

The fix

Test for null first:

if (amount == null || amount < 0) {
    return 0;
}
return amount;

Now you try

Fill in the body of pointsFor on FlatScore. The abstract ScoreRule is already provided; do not change it. The hidden tests call pointsFor directly and also through a ScoreRule-typed variable.

Learn more

The challenge

Finish FlatScore so it overrides pointsFor from the provided abstract ScoreRule.

Examples:

  • pointsFor(10) builds 10
  • pointsFor(null) or a negative amount builds 0
  • label(10) on the subclass builds score:10

Requirements:

  1. scoresAPositiveAmount should pass: pointsFor(10) returns 10.
  2. treatsNullAndNegativeAsZero should pass: null, zero and negative amounts all return 0.
  3. labelUsesTheOverride should pass: the base label() reads pointsFor on the subclass.
  4. worksThroughTheAbstractType should pass: a ScoreRule variable holding a FlatScore still runs the override.

Starter code

public class AS_7C3A1E904B2D_FlatScore extends AS_7C3A1E904B2D_ScoreRule {
}

Related drills

Try this drill free

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

‹ Static versus instance members