Abstraction means exposing only the essential, relevant details of something while hiding the underlying complexity. It's closely related to encapsulation, but the emphasis is different: encapsulation is about protecting data by controlling access; abstraction is about simplifying a concept by modeling only what matters for the current purpose and ignoring the rest.
When you drive a car, you interact with an abstraction: a steering wheel, pedals, and a gear selector. You don't need a mental model of the engine's internal combustion cycle — that complexity is abstracted away behind a simple driving interface.
In code, abstraction happens at multiple levels:
- Within a class: public methods represent what an object can do; private implementation details represent how — callers only need to understand the 'what'.
- Across a system: an
EmailSenderinterface might abstract over the fact that, underneath, one implementation uses SMTP and another uses a third-party API — calling code just callssend()without caring how.
// Abstraction: callers only need to know this interface exists
class PaymentProcessor {
function charge(amount, cardToken) {
// Internally: validates card, calls a bank API, handles retries,
// logs the transaction, converts currency if needed...
// None of this complexity is visible to the caller.
}
}
processor.charge(49.99, token) // simple, abstracted interface
Good abstraction is a skill, not just a mechanism — it requires judgment about which details are 'implementation noise' that should be hidden, and which are essential enough that the caller genuinely needs to know about them. Over-abstracting can hide information a caller actually needs; under-abstracting leaks unnecessary complexity into every caller.