Interfaces and abstract classes look similar from a distance: both let you define a contract that other code agrees to before every detail of the implementation exists. The difference that actually matters day to day is not philosophical, it is mechanical. An interface carries no state and, in most languages, no working code. An abstract class can carry both, and a class can usually only extend one of them at a time. That single-inheritance limit, more than any theory, decides which one fits a given design.
What changed in 2026
- TypeScript interfaces are structural, not nominal. A class does not need to declare that it implements an interface; if it has the right shape, it satisfies the interface. Developers coming from Java or C#, where implementing an interface is an explicit declaration, often get this nuance wrong at first.
- Default methods blurred the old rule. Modern versions of Java and C# both allow interfaces to include method bodies. The presence of code is no longer the clean dividing line it once was; the absence of state still is.
- Composition over inheritance is the default guidance now. Most 2026 style guides favor small interfaces plus composition over deep abstract class hierarchies, reserving abstract classes for a narrower set of cases where subclasses genuinely share behavior.
The core difference
An interface is a contract: it lists what a class must be able to do, with no state and, traditionally, no implementation. An abstract class is a partial implementation: it can hold fields, provide a constructor, and give subclasses real, working methods for free, in addition to declaring methods each subclass must fill in itself.
|
Interface |
Abstract class |
| Implementation |
None, or default methods in some languages |
Can include real method bodies |
| State (fields) |
No |
Yes |
| Multiple inheritance |
A class can implement many |
A class can extend only one, in most languages |
| Relationship implied |
Can-do (capability) |
Is-a (shared identity) |
| Constructor |
No |
Yes |
The same problem, solved both ways
// Interface: only the shape is shared
interface Shape {
area(): number;
}
class Circle implements Shape {
constructor(private r: number) {}
area() { return Math.PI * this.r ** 2; }
}
// Abstract class: shape AND shared behavior
abstract class ShapeBase {
abstract area(): number;
describe() { return `Area is ${this.area().toFixed(2)}`; } // shared, real code
}
class Square extends ShapeBase {
constructor(private side: number) { super(); }
area() { return this.side ** 2; }
}
describe() is written once, in the abstract class, and every subclass inherits it for free. An interface alone cannot give you that; each implementer would need to write its own version.
When to use which
- Multiple unrelated classes need to promise the same capability, and nothing else in common. Use an interface.
- Subclasses share meaningful, real logic, not just a method signature. Use an abstract class.
- The language has no multiple inheritance and the class already extends something else. An interface is the only option left.
- Unsure which fits. Start with an interface; it is easier to add a shared base class later than to remove one that other code already depends on.
Common mistakes
- Using an abstract class purely to share a couple of helper methods that could just as easily be a plain function or a composed utility.
- Building a fifteen-method interface that no single implementer needs in full. This is exactly what the interface segregation idea in SOLID principles explained in 2026 addresses: split it into smaller, role-specific interfaces instead.
- Assuming interfaces carry no behavior in every language. Java and C# both allow default interface methods now, so check the language before assuming.
FAQ
Can a class implement an interface and extend an abstract class at the same time?
In most mainstream languages, yes. A class can extend one abstract class and implement any number of interfaces at the same time.
Does duck typing make this distinction irrelevant in JavaScript?
Partly. Plain JavaScript has neither construct natively, and TypeScript adds interfaces as a compile-time-only structural contract. See what duck typing is for how JavaScript gets by without either.
Which one should a beginner learn first?
Interfaces. They force you to think about the contract before the implementation, which is the more transferable skill across languages and frameworks.
Do interfaces hurt performance compared to abstract classes?
For the vast majority of applications, no meaningful difference exists. Choose based on the design problem in front of you, not on a performance concern you have not actually measured.
Where to go next