An interface is a pure contract: method signatures, nothing else. Sometimes you want the contract AND a shared chunk of behavior or shared fields. Abstract classes are the language feature for that half-way house: a class that defines a contract (with abstract methods) AND can hold real code, real fields, and even a real constructor.
Mark a class abstract and it becomes a contract that other classes can build on, but it can no longer be created with new on its own:
public abstract class Shape {
public abstract Decimal getArea();
}
The body of getArea() is missing on purpose. Every concrete class that extends Shape must provide one, or the compiler refuses to build the class. Trying to write new Shape() is a compile error too: the contract is not done yet, so there is nothing to make.
Unlike an interface, an abstract class can also have a method with a body. Concrete subclasses inherit that method for free, and only the abstract ones need to be filled in:
public abstract class Shape {
public String name;
public Shape(String name) {
this.name = name;
}
public String describe() {
return this.name + ' has area ' + this.getArea();
}
public abstract Decimal getArea();
}
A Rectangle only has to write getArea(). The describe() method comes for free, and the constructor stores the name. The class is still abstract because getArea() is not implemented yet, so the compiler will not let anyone write new Shape(...) directly.
A concrete class extends the abstract class and provides a body for every abstract method, the same way a child class provides a body for a virtual method:
public class Rectangle extends Shape {
public Decimal width;
public Decimal height;
public Rectangle(String name, Decimal width, Decimal height) {
super(name);
this.width = width;
this.height = height;
}
public override Decimal getArea() {
return this.width * this.height;
}
}
override is required, just like with a regular virtual method. The compiler now lets you write new Rectangle('Square', 5, 5) because every abstract method has a body.
Both let you write code that works with many types. The two questions to ask are simple:
abstract class. A Shape with a real name field, a real constructor, and a working describe() is a perfect abstract class.interface. A NotificationChannel for email and SMS implementations does not share any code, so an interface is the right tool.In practice, the two work together. A class can extends one abstract class AND implements any number of interfaces, picking up shared behavior and signing additional contracts at the same time.
In the exercise editor every class is already virtual by default, and you cannot write abstract on the class itself. You CAN write abstract on a method, and that is what the exercise uses. The methods a child class overrides still need override, exactly like in a real org.
Abstract classes are how frameworks hand you a partially-built class and ask you to fill in the missing piece. The Salesforce Batchable and Queueable classes are abstract, with abstract methods like execute or start for the developer to implement. The framework gives you all the bookkeeping, you write the work.