𝗔𝗯𝘀𝘁𝗿𝗮𝗰𝘁𝗶𝗼𝗻 𝗶𝗻 𝗢𝗢𝗣: 𝗛𝗶𝗱𝗶𝗻𝗴 𝗖𝗼𝗺𝗽𝗹𝗲𝘅𝗶𝘁𝘆
You drive a car using a few simple actions. You press the gas pedal. You turn the wheel. You hit the brakes.
You do not need to know how fuel enters the engine. You do not need to understand how pistons move or how gears shift. The car hides those details from you. You use a simple interface to control a complex machine.
Software works the same way.
Think about sending an email. You call one command: emailService.send().
Behind the scenes, many things happen:
- The system validates the address.
- It creates an SMTP connection.
- It authenticates with a provider.
- It builds the message.
- It handles retries if the first attempt fails.
You do not need to see these steps. You only care that the email sends.
If you did not use abstraction, your code would look like this:
- connect()
- authenticate()
- buildMessage()
- sendMessage()
- disconnect()
Doing this every time creates problems. Every part of your code knows too much. If you change your email provider, you must update every single line of code that sends mail. Your system becomes hard to change.
Abstraction solves this. It shows what an object does but hides how it works.
You expose a simple interface. The caller stays focused on the task. The implementation stays hidden. This keeps your code decoupled and easy to maintain.
People often confuse Abstraction with Encapsulation.
Encapsulation asks: Who can change this data? It protects the internal state. Abstraction asks: What details does the user need to see? It hides complexity.
They work together to build better systems.
Next, we will look at Inheritance. We will answer one question: If objects share behavior, do you need to write the same code twice?