---
title: "Interfaces and abstract classes in Apex"
url: "https://trailassembly.com/apex-interfaces-and-abstract/"
topic: "Apex and Development"
published: "2026-09-18T04:52:38+00:00"
updated: "2026-10-06T13:57:45+00:00"
---

# Interfaces and abstract classes in Apex

**The quick version:** use an interface when you need a contract that several unrelated classes can satisfy, and an abstract class when the implementations share real code or state. Apex has no multiple inheritance, so a class extends one abstract class but implements as many interfaces as you like. In practice, most Apex you write will implement a platform interface rather than define one, and those are the ones worth learning properly.

## The mechanical differences

- An interface declares method signatures and nothing else. No fields, no constructors, no bodies.

- Interface methods are implicitly public or global. You cannot make one private.

- An abstract class can hold fields, constructors, concrete methods and abstract methods together.

- Apex methods are not overridable by default. A concrete method in an abstract class needs `virtual` before a subclass can `override` it, and the subclass must say `override` explicitly.

- A class can implement many interfaces and extend exactly one class.

```apex
public interface TaxCalculator {
    Decimal calculate(Decimal amount, String country);
}

public abstract class BaseNotifier {
    protected String channel;

    protected BaseNotifier(String channel) {
        this.channel = channel;
    }

    public virtual String formatSubject(String raw) {
        return '[' + channel + '] ' + raw;
    }

    public abstract void send(List<String> recipients, String body);
}
```

The notifier has a constructor, a field every subclass needs, and a default rule any subclass may replace. None of that fits in an interface, which is the signal that an abstract class is correct.

## Choosing between them

Ask what the implementations have in common. If the answer is “a shape”, use an interface. If the answer is “a shape and about forty lines of identical code”, use an abstract class.

Interfaces win when the implementing classes are unrelated, when a class needs to play several roles at once, and when you want to mock the dependency in a test. A selector behind an interface can be stubbed with `Test.createStub`, which turns a slow test into a fast one.

Abstract classes win when there is genuine shared behaviour, when subclasses need protected state, and when you want to force construction through a constructor that validates its arguments.

The combination is fine: an interface for the contract, an abstract base implementing the boring half, concrete classes filling in the rest. Do not start there. Promote to a base class once you have written the same code twice.

## The platform interfaces worth knowing

**`Database.Batchable<SObject>`** with its trio of `start`, `execute` and `finish`, plus the marker interfaces that change what the job may do: `Database.Stateful` to keep instance variables across chunks, `Database.AllowsCallouts` to make HTTP requests, and `Database.RaisesPlatformEvents` so failures surface as `BatchApexErrorEvent` records you can subscribe to.

**`Queueable`** for asynchronous work with a job id and chaining. You get 50 [queueable](https://trailassembly.com/apex-choosing-async/) jobs enqueued per transaction.

**`Finalizer`**, attached to a queueable with `System.attachFinalizer`. It runs even when the queueable threw an unhandled exception or hit a limit, which makes it the only reliable place to record that an asynchronous job died.

**`Schedulable`**, a single `execute` method, usually doing nothing but launching a batch.

**`Comparable`** and **`Comparator`** for sorting. `Comparable` puts the order inside the class; `Comparator` keeps it outside, which lets you sort the same type several ways and works on classes you did not write.

**`Callable`** is the interesting one. It gives you a single `call(String action, Map<String, Object> args)` method, which lets one package invoke another’s code without a compile time dependency. If you build managed packages that optionally talk to each other, this is the mechanism.

**`Messaging.InboundEmailHandler`** for email services, **`HttpCalloutMock`** for testing callouts, **`System.StubProvider`** for building your own mocking layer, and **`Iterator`** plus **`Iterable`** when a batch needs to process something other than a query result.

## Where people go wrong

**An interface with one implementation.** Written on the theory that a second will arrive, and it rarely does. Now every reader follows an extra hop to the code. Add it when the second implementation exists, or when you need it for testing.

**An abstract class used as a namespace.** If it has no abstract methods and no state, it is a class with static methods and should say so.

**Deep hierarchies.** Three levels of abstraction in Apex is almost always one too many. The platform does not reward it and debugging it is miserable.

**Interfaces on sObjects.** You cannot. sObjects are platform types and cannot implement your interface, which is why sorting or polymorphism over records goes through a wrapper class instead.

## Frequently asked

**Can an interface extend another interface?** Yes, and an interface may extend several. That is the closest Apex gets to multiple inheritance.

**Can an abstract class implement an interface without defining every method?** Yes. Leave the remainder abstract and the concrete subclass supplies them.

**Do I need `global` for a [managed package](https://trailassembly.com/1gp-vs-2gp/)?** Only for members subscribers must see. A `global` interface is permanent and its methods can never be changed, so publish as little as you can live with.

**Can I instantiate an abstract class?** No. `Type.forName` on one returns the type, but calling `newInstance()` throws at runtime rather than failing to compile.

---

Source: https://trailassembly.com/apex-interfaces-and-abstract/
Trail Assembly — independent Salesforce write-ups.
