Learn Apex
Access modifiers
Pair short explanations with real-looking Apex — then use the explorer to connect each keyword to who can call it.
Interactive

In Apex, modifiers control who can reference a member or type. Start restrictive (private), then widen only when needed.

A practical rule: expose a small public surface (methods callers need), keep validation and formatting in private helpers — that makes large classes easier to read and safer to change.

Pattern: hide helpers, expose intent

Callers only see save()— the messy rules stay inside the class.

public class AccountService {
    public void save(Account a) {
        normalizeName(a);
        if (!isValid(a)) {
            return;
        }
        insert a;
    }

    private void normalizeName(Account a) {
        if (a.Name != null) {
            a.Name = a.Name.trim();
        }
    }

    private Boolean isValid(Account a) {
        return a.Name != null && a.Name.length() > 0;
    }
}

Pattern: extend behavior with protected

Subclasses can reuse a hook without opening it to unrelated classes in the org.

public virtual class BaseProcessor {
    protected virtual void beforeInsert(Account a) {
        // default: no-op
    }
}

public class StrictProcessor extends BaseProcessor {
    protected override void beforeInsert(Account a) {
        a.Name = (a.Name == null) ? 'Required' : a.Name;
    }
}

Pick a modifier

Example line
private Integer secret = 1;

Only this class can use it — the tightest visibility.

Who can access it?

AudienceOK?
Same class
Subclass (extends)
Other classes in your org
Subscriber / other namespace (e.g. customer org)

Simplified mental model for learning — real org security also includes sharing, profiles, and managed-package namespaces.

virtual & override (pair with visibility)

virtual on a method allows subclasses to replace it with override. The subclass still has to respect visibility: it cannot override what it cannot see.

public virtual class DiscountEngine {
    public virtual Decimal rate() {
        return 0.05;
    }
}

public class PartnerDiscount extends DiscountEngine {
    public override Decimal rate() {
        return 0.15;
    }
}