The Apex Master Class

When to Use the Private Keyword in Apex (Ep. 25)

4 min read

Subscribe on YouTube

Your Default Setting

Last of the four access modifiers, and the one you should be reaching for most.

private means only this class can use it. Not subclasses. Not other classes in your org. Just the class it’s declared in.

It’s also what Apex assumes if you don’t say anything, which tells you something about what the language thinks the sensible default is.

Apex
public class EmailService
{
    private String fromAddress = 'noreply@codingwiththeforce.com';

    public void sendWelcomeEmail(Contact cont)
    {
        String body = buildEmailBody(cont);
        deliver(cont.Email, body);
    }

    private String buildEmailBody(Contact cont)
    {
        return 'Welcome, ' + cont.FirstName + '!';
    }

    private void deliver(String toAddress, String body)
    {
        //sending logic
    }
}

One public door in. Everything else is machinery nobody outside needs to see.


Why Bother Hiding Things?

When you’re new, this genuinely feels like pointless bureaucracy. It’s your own org. Who exactly are you hiding your methods from?

Fair question, and here’s the honest answer: you’re not hiding them, you’re protecting your own freedom to change them.

Say buildEmailBody() is private. Six months from now you want to rewrite it, rename it, split it in two, delete it entirely. Can you? Yes, instantly, because you already know every place it’s called: this file. You can see all of them from where you’re sitting.

Now say it was public. Same six months, but now anything in the org might be calling it. Before you touch a line, you’re searching the entire codebase, checking every caller, and hoping there isn’t a managed package or an old Visualforce page quietly depending on it.

Same method. Same code. Completely different cost to change, purely because of one keyword.

That’s the entire argument for private, and it’s a good one.


“But I Need It Public For My Tests”

Ah. This one. This is the reason most private methods quietly become public, and I want to head it off now.

Test classes can’t call private methods, so the instinct is to make everything public so you can test it directly. Please don’t. There’s a proper tool for this:

Apex
@TestVisible
private String buildEmailBody(Contact cont)
{
    return 'Welcome, ' + cont.FirstName + '!';
}

@TestVisible makes a private member reachable from test classes and only from test classes. Your production code still can’t touch it. You get your test coverage without widening your public interface.

Works on variables too, which is handy for checking internal state after a method runs.

Small caveat worth mentioning: if you find yourself slapping @TestVisible on everything, that’s usually a sign the class is doing too much. Testing through the public interface is generally the better path, and if that’s awkward, the design is telling you something. But when you do need it, it’s the right tool.


Private Inner Classes

One more genuinely useful trick. You can put a class inside another class, and mark it private:

Apex
public class OpportunityReportService
{
    //Only this class needs to know this shape exists
    private class ReportRow
    {
        private String accountName;
        private Decimal totalAmount;
    }

    public void buildReport()
    {
        ReportRow row = new ReportRow();
        //...
    }
}

Brilliant for little data holder types that exist purely to serve one class. Keeps them close to where they’re used instead of cluttering your org with a ReportRow class that means nothing on its own.


All Four, Side By Side

private – this class only. Your default.
protected – this class and its subclasses. For base classes you intend to be extended.
public – anything in your namespace. For a class’s real interface.
global – anything anywhere. Only when the platform makes you.

The habit to build: start private, open up only when something actually needs it. It costs nothing to loosen later, and it costs a lot to tighten.


What’s Next

That’s access modifiers done. You now know how to build classes, give them variables and methods, construct them, instantiate them, store things in collections, and control who can reach what.

What we haven’t done is make your code make decisions. Every example so far runs straight through, top to bottom, every time. In the next episode we fix that with conditional statements.

See you next time!


Get Coding With The Force Merch!!

We now have a redbubble store setup so you can buy cool Coding With The Force merchandise! Please check it out! Every purchase goes to supporting the blog and YouTube channel.

Get Shirts Here!
Get Cups, Artwork, Coffee Cups, Bags, Masks and more here!


Check Out More Coding With The Force Stuff!

If you liked this post make sure to follow us on all our social media outlets to stay as up to date as possible with everything!

Youtube
Patreon
Github
Facebook
Twitter
Instagram


Salesforce Development Books I Recommend

Advanced Apex Programming
Salesforce Lightning Platform Enterprise Architecture
Mastering Salesforce DevOps

Good Non-SF Specific Development Books:

Clean Code
Clean Architecture