Abstraction??
The poster child for abstraction is mathematics. And let's be honest, mathematical abstraction is notoriously difficult. If you can actually enjoy it, you have a real talent for math.
Because it has such a bad reputation, people assume programming abstraction must be hard, too.
In a way, they're the same. But in another, they are completely different.
Programming Abstraction is Our Daily Life
Abstraction in programming is our everyday life. It's our language.
What "abstraction" means in programming is the same as how we normally talk. To be precise, it's the method for expressing the 'Contracts' I find so important.
Let's say I'm making plans with a friend. I can tell them, "Come by car tomorrow." A totally normal phrase, right? But that is programming abstraction.
The Contract is: You must arrive at the meeting place tomorrow, and you must come by car.
That's it. Those are the only two conditions. As long as I fulfill those two, the specific details of how are completely up to me. My friend doesn't care if I take a taxi, a bus, or my own car.
So what does it mean to not use abstraction in programming?
It's like your friend saying, "Tomorrow, come in your Red 2023 Ford Mustang GT, license plate 8XN-4Y2."
If you talked like that in real life, people would think you're a psycho. And the biggest problem with this "contract" is that I must come in that specific Ford Mustang.
But what if I sold it? What if it's in the shop for repairs? What if I bought a new car? What if I left my car in another city? It becomes difficult to fulfill the contract, and the truly important part—showing up to the meeting—is blocked by a trivial constraint.
This happens because your friend knows the specific details of the car you own.
"Just make sure it's a car, and you figure out the rest." That's how we normally talk.
"Turn on your laptop so we can video call." "Grab a spoon so we can eat." "Check your texts." "The car broke down, so take it to a repair shop." All of this everyday language is abstraction. It's completely natural to us.
But imagine if people said this instead:
"Turn on your M2 MacBook Air for the video call." "Grab that specific spoon from the Chinese restaurant." "Check your texts on your iPhone 14." "Your Red 2023 Ford Mustang GT, license plate 8XN-4Y2, is broken, so take it to the specific Ford dealership on 123 Main Street to get it fixed."
That's not abstraction; that's defining a contract with needless, suffocating detail. It's a contract you can't fulfill if circumstances change later. Besides, who even talks like that?
But in programming, we make this mistake all the time.
Let's translate that "psycho conversation" into code.
// The concrete implementation: a Ford Mustang GT
class FordMustangGT {
public void driveTo(String destination) {
System.out.println("Driving the Ford Mustang GT smoothly to " + destination + ".");
}
}
// The requester: demands a specific 'FordMustangGT'
class Person {
public void goToAppointment(FordMustangGT myCar) {
// This code can only talk to a 'FordMustangGT'.
myCar.driveTo("the meeting spot");
}
}
// The execution code
public class Main {
public static void main(String[] args) {
Person person = new Person();
FordMustangGT mustang = new FordMustangGT();
person.goToAppointment(mustang);
}
}
Writing code like this is often seen as perfectly natural. Isn't that weird? The very way of speaking that would get you labeled a psycho in real life is considered normal in programming.
Now let's change it to a natural, everyday conversation.
// 1. The Contract (Interface): Defines the "must be able to move" contract
interface Car {
void moveTo(String destination);
}
// 2. The various implementations that honor the contract
class MyFordMustang implements Car {
@Override
public void moveTo(String destination) {
System.out.println("Driving my Ford Mustang to " + destination + ".");
}
}
class Taxi implements Car {
@Override
public void moveTo(String destination) {
System.out.println("Calling an Uber to get to " + destination + ".");
}
}
class Bus implements Car {
@Override
public void moveTo(String destination) {
System.out.println("Taking the 143 bus to " + destination + ".");
}
}
// 3. The requester: Depends only on the 'Car' contract
class Person {
public void goToAppointment(Car anyCar) {
// This code can talk to ANY object that honors the 'Car' contract.
anyCar.moveTo("the meeting spot");
}
}
// 4. The execution code
public class Main {
public static void main(String[] args) {
Person person = new Person();
// Today, I'll use my own car.
person.goToAppointment(new MyFordMustang());
// Tomorrow, I'll take a taxi.
person.goToAppointment(new Taxi());
// The day after, I'll take the bus.
person.goToAppointment(new Bus());
}
}
I'll admit, writing the code this way can feel like a pain. It seems like more effort, so you're tempted to just write the specific, concrete code. But this "good" code is just a direct translation of our natural, everyday life. I think it's strange to treat the same concept so differently.
Conclusion
Abstraction is the natural language we use every day.
Next time, I'll explain the specific benefits of using abstraction like this.
Top comments (0)