ApexSensei

Drills Classes & objects

virtual, override and super

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

Extend a provided `Vehicle` class with a `Car` subclass that overrides `describe()`. The override must call `super.describe()` to read the base label, then wrap it as `Car (from Vehicle)`. Keep the given class names so the hidden tests can find them.

Lesson

Why this matters

In Apex, a method on a base class is sealed by default. Nothing on a subclass can replace it. If you want a subclass to swap in its own behaviour and still reuse the base work, three keywords have to line up: virtual on the base method, override on the subclass, and super to call back into the base.

The smallest working example

public virtual class Vehicle {
    public virtual String describe() {
        return 'Vehicle';
    }
}

public class Car extends Vehicle {
    public override String describe() {
        return 'Car (from ' + super.describe() + ')';
    }
}

new Car().describe() returns Car (from Vehicle).

Name the parts

  • **virtual** on the base method says "a subclass is allowed to replace me".
  • **extends** on the subclass links the two classes.
  • **override** on the subclass method says "I am replacing the base version". Do not add virtual again.
  • **super.describe()** calls the base version from inside the override, so you can wrap it instead of repeating it.

A common wrong version

public class Car extends Vehicle {
    public virtual String describe() {
        return 'Car (from ' + describe() + ')';
    }
}

Two bugs. virtual on the subclass should be override, so the compiler rejects the class. And describe() on its own calls itself, which would loop forever if it compiled. The call to the base must be super.describe().

The fix

Use override, then build the label from super.describe():

public override String describe() {
    return 'Car (from ' + super.describe() + ')';
}

Now you try

Fill in the Car body in the starter. The base Vehicle class is already provided; do not change it. The hidden tests call both new Car() and a Vehicle-typed reference pointing at a Car.

Learn more

The challenge

Finish the Car subclass so describe() wraps the base label.

Examples:

  • new AS_1860C37D10D4_Vehicle().describe() builds Vehicle
  • new AS_1860C37D10D4_Car().describe() builds Car (from Vehicle)
  • A Vehicle-typed variable holding a Car still runs the override

Requirements:

  1. baseReturnsVehicle should pass: the provided Vehicle on its own still returns Vehicle.
  2. carOverridesWithSuper should pass: new Car().describe() returns Car (from Vehicle) by calling super.describe().
  3. dynamicDispatchHitsOverride should pass: a Vehicle variable holding a Car runs the override.
  4. baseAndChildAreDistinct should pass: Vehicle and Car return different labels.

Starter code

public class AS_1860C37D10D4_Car extends AS_1860C37D10D4_Vehicle {
}

Related drills

Try this drill free

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

‹ Interface with two implementations · Constructor chaining with this(...) ›