Chapter[15]: Abstraction, Abstract Class, and Interface: The OOP Trio Explained: Part 1
Before moving to more complex examples of Abstraction(abstract class and Interface), let’s first dive into the basic one, the next 2 Part of this short series would be more complex, as we will be moving again to payment systems.
What is Abstraction?
Think of abstraction as the art of hiding unnecessary details while showcasing only the essentials. It’s like driving a car: you don’t need to know how the engine works, but you know pressing the accelerator makes it go vroom.
In programming, abstraction allows you to focus on what an object does instead of how it does it.
and there might be some confusion with Encapsulation, as initially it was hard for me to distinguish between them, let me clear it up a little bit, then we will move forward:
- Encapsulation hides the data.(restricts direct access).
- Abstraction hides the implementation.
Both aim to show only what’s necessary, but encapsulation is more about safeguarding internal states, while abstraction is about simplifying usage. Does this clear it up? 😊
Here’s a textual representation to visualize the relationship between classes, subclasses, abstract classes, and their subclasses:
Regular Class and Subclasses
Class: Animal
+---------------------+
| Animal |
|---------------------|
| - name: String | <-- Attributes (private variables)
| - age: int |
|---------------------|
| + eat(): void | <-- Methods (public behaviors)
| + speak(): void |
+---------------------+
| (Inheritance)
v
Subclass: Dog
+---------------------+
| Dog |
|---------------------|
| + speak(): void | <-- Implements speak method
+---------------------+
| (Inheritance)
v
Subclass: Cat
+---------------------+
| Cat |
|---------------------|
| + speak(): void | <-- Implements speak method
+---------------------+
Abstract Class and Subclasses
Abstract Class: Animal
+---------------------+
| Animal |
|---------------------|
| + speak(): void | <-- Abstract method (no implementation)
|---------------------|
| + eat(): void | <-- Concrete method (shared implementation)
+---------------------+
| (Inheritance)
v
Subclass: Dog
+---------------------+
| Dog |
|---------------------|
| + speak(): void | <-- Implements abstract method
+---------------------+
| (Inheritance)
v
Subclass: Cat
+---------------------+
| Cat |
|---------------------|
| + speak(): void | <-- Implements abstract method
+---------------------+
Key Notes:
- Regular Class: Can be instantiated directly (e.g.,
Dog dog = new Dog();
). - Abstract Class: Cannot be instantiated directly. Its subclasses must implement all abstract methods unless they’re abstract themselves.
- Subclasses: Inherit attributes and methods from their parent class but can also have their own unique attributes and behaviors.
Example in Code
Let’s say we’re building a zoo system. Here’s an abstract example:
abstract class Animal {
abstract void speak(); // No implementation here - it's abstract!
void eat() { // A concrete method - all animals eat.
System.out.println("This animal eats food.");
}
}
Here, Animal
provides a generic blueprint for all animals. It says, “Hey subclasses, you must define the speak()
method, but I’ll handle the eat()
logic for you.”
Abstract Classes: A Guided Blueprint
An abstract class is like a semi-finished building. It has a basic structure but leaves room for customization. You can mix abstract methods (pure ideas) with concrete methods (actual implementations).
Example
abstract class Animal {
abstract void speak(); // Must be implemented by subclasses.
void eat() { // Shared implementation for all animals.
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void speak() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
void speak() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.speak(); // Output: Woof!
dog.eat(); // Output: This animal eats food.
Animal cat = new Cat();
cat.speak(); // Output: Meow!
}
}
Here, Dog
and Cat
implement their versions of speak()
while reusing the eat()
method from the Animal
class.
Interface: The Ultimate Contract
Now, let’s level up. What if we want to ensure unrelated classes follow the same set of rules? Enter the interface, a 100% abstraction tool. It’s like a contract: “If you implement me, you must provide these methods.”
Example
interface Animal {
void speak(); // No implementation here - just the contract!
}
class Dog implements Animal {
public void speak() {
System.out.println("Woof!");
}
}
class Cat implements Animal {
public void speak() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.speak(); // Output: Woof!
Animal cat = new Cat();
cat.speak(); // Output: Meow!
}
}
Notice the differences:
Animal
is now an interface, not a class.- We’re enforcing the
speak()
contract but leaving no room for shared logic likeeat()
.
Abstraction vs Abstract Class vs Interface
Here’s a breakdown in a clean, structured format for easier understanding:
1. Definition
- Abstraction: Hiding unnecessary details and exposing only essential features.
- Abstract Class: A semi-finished class that can have both implemented (concrete) methods and unimplemented (abstract) methods.
- Interface: A fully abstract contract that defines methods a class must implement.
2. Implementation
- Abstraction: It’s a concept, not tied to specific code.
- Abstract Class: Can have a mix of abstract methods (no implementation) and concrete methods (with implementation).
- Interface: Only abstract methods, making it pure abstraction.
3. Fields/Properties
- Abstraction: Not directly applicable to fields or properties.
- Abstract Class: Can have instance variables and constants.
- Interface: Only constants (static and final by default).
4. Multiple Inheritance
- Abstraction: Not a direct feature, but the principle can work across multiple entities.
- Abstract Class: Not supported in Java; a class can inherit only one abstract class.
- Interface: Supported in Java via multiple interfaces.
5. Usage
- Abstraction: A general OOP principle to simplify and modularize code.
- Abstract Class: Used to share functionality among related classes, with some methods left for subclasses to define.
- Interface: Used to enforce a contract across unrelated classes or when multiple inheritance is needed.
When to Use What?
- Abstraction: The overarching concept to design clean, modular systems.
- Abstract Class: Use it when you have common functionality to share across related classes. Think of it as the base for a group of similar objects.
- Interface: Use it when you want completely unrelated classes to share a common contract, or when you need multiple inheritance.
Bringing It All Together
To summarize:
- Abstraction is the goal: to simplify your code and make it more modular.
- Abstract Classes are the tool for partial abstraction, allowing shared logic with some methods left for subclasses, abstract class extends.
- Interfaces are the tool for pure abstraction, enforcing a strict “contract” for any class that implements them, it Implements.
HINT: When creating a class which is public class baseZoo, remove the public with abstract and now it’s a abstract class, which is abstract class baseZoo, you can now drop unimplemented methods into it.
check and Download the codes here
You can now catch the podcast on YouTube too!
.
.
.
Happy Coding!