Inheritance is powerful, but every child can only extend one parent class. Sometimes the right idea is not "is a more specific kind of" but rather "can do this job". A class that wants to do that job can be totally unrelated to another class that also wants to do it. Interfaces are the language feature that lets unrelated classes share a contract.
An interface is a list of method signatures with no bodies. Any class that wants to honor the contract promises to write all of them:
public interface NotificationChannel {
Boolean send(String toAddress, String message);
}
The interface says what a notification channel must do, not how. An email channel, an SMS channel, and a push channel can all implement NotificationChannel even though they share no parent class.
A class uses implements to sign the contract, and it has to provide every method the interface lists:
public class EmailNotification implements NotificationChannel {
public Boolean send(String toAddress, String message) {
// email-specific code here
return true;
}
}
public class SmsNotification implements NotificationChannel {
public Boolean send(String toAddress, String message) {
// sms-specific code here
return true;
}
}
Both classes now have a send(String, String) method that returns Boolean. The compiler enforces that the signature matches exactly.
The real power of an interface shows up when you hold different implementations in one list:
List<NotificationChannel> channels = new List<NotificationChannel>{
new EmailNotification(),
new SmsNotification()
};
for (NotificationChannel channel : channels) {
channel.send('user@example.com', 'Welcome!');
}
The loop never asks which kind of channel it has. It just calls send(...) and lets the object decide. The same idea powered the polymorphism you saw in the previous lesson; interfaces let you apply that pattern to classes that do NOT share a parent.
Both let you write code that works with many types, and both are contracts. The differences matter when you reach for them:
extends one parent class but implements many interfaces. Use interfaces when two unrelated abilities should both apply.In the exercise editor the same rules as the previous lessons apply. Writing virtual on a class is a compile error (classes are by default virtual), but interface, implements, and the interface methods all behave exactly like in a real org.
Frameworks in Salesforce lean on interfaces. The batch Apex framework you may have seen, the platform event publishing pattern, and the queueable / schedulable job system are all interface-driven. When a framework says "write a class that implements Queueable and provides an execute method", it is handing you an interface to sign.