# Revisiting the Four Pillars of Object-Oriented Programming

Sometimes I dive so deep into software development details that I forget the basics. Fundamentals become second nature, slipping beneath my conscious awareness. Recently, a memory from one of my first software development interviews popped into my head, reminding me of a seemingly simple question about the **Four Pillars of Object-Oriented Programming**. Back then, I nailed it. Today? I'd hesitate a bit. I asked a couple of other experienced engineers as well and they struggled too! So, let's refresh our memory together using some animal examples.

## Abstraction

**Abstraction** simplifies complexity by modeling only what's necessary, hiding the underlying details. Think about animals, you don't need to know everything about an animal, just the behaviors important to your application.

```csharp
abstract class Animal
{
    public abstract void MakeSound();
}
class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Woof!");
    }
}
class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("Meow!");
    }
}
```

Here, the `Animal` class is abstract, meaning you can't create an "Animal" directly, only specific animals like dogs or cats. It keeps things simple: you're just interested in animals making sounds.

## Encapsulation

**Encapsulation** bundles data and methods operating on that data within one unit, keeping things safe and secure. Consider your checking account: you don't let anyone directly change your balance, you control it through safe methods.

```csharp
class CheckingAccount
{
    private decimal balance;

    public void Deposit(decimal amount)
    {
        if (amount > 0) balance += amount;
    }

    public void Withdraw(decimal amount)
    {
        if (amount > 0 && amount <= balance) balance -= amount;
    }

    public decimal GetBalance()
    {
        return balance;
    }
}
```

Your balance is encapsulated, ensuring only valid transactions modify it. This stops someone from just setting any balance they like. And yes, I know this isn't animal-related, I couldn't think of a clearer animal analogy! Leave me alone.

## Inheritance

**Inheritance** lets classes reuse properties and behaviors from other classes. Think of how all birds can fly, but each might add unique features. Ignore penguins.

```csharp
class Bird
{
    public void Fly()
    {
        Console.WriteLine("Bird is flying.");
    }
}
class Sparrow : Bird
{
    public void Chirp()
    {
        Console.WriteLine("Sparrow chirps.");
    }
}
```

Here, `Sparrow` inherits the `Fly()` method from `Bird` and adds a unique `Chirp()` method. Inheritance makes your classes reusable and easy to extend.

## Polymorphism

**Polymorphism** allows objects of different classes to behave differently even though they're accessed through a common interface. Think about how each animal has its way of eating, but your code treats them uniformly.

```csharp
class Animal
{
    public virtual void Eat()
    {
        Console.WriteLine("Animal eats.");
    }
}
class Lion : Animal
{
    public override void Eat()
    {
        Console.WriteLine("Lion eats meat.");
    }
}
class DieselTheDog : Animal
{
    public override void Eat()
    {
        Console.WriteLine("Diesel my dog eats first and asks questions later.");
    }
}
class Program
{
    static void Main(string[] args)
    {
        Animal lion = new Lion();
        Animal dog = new DieselTheDog();

        lion.Eat(); // Lion eats meat.
        dog.Eat(); // Diesel my dog eats first and asks questions later.
    }
}
```

The `Eat()` method demonstrates polymorphism. Your application knows animals eat, but each animal type does it differently. This lets you handle many animals uniformly.

## Why Did I Forget These Pillars?

Over years of practice, these principles became second nature rather than explicit practice. It's easy to overlook foundational ideas when you're busy handling complex problems every day. Revisiting basics regularly helps keep your understanding sharp and clear.

## Why Remembering OOP Pillars Matters

While the examples here are intentionally simple, revisiting fundamental OOP concepts helps clarify your thought processes, improving your class designs and overall code quality. Clear class design also makes your communication better with teammates and junior developers, simplifying debugging and enhancing maintainability.

These pillars are practical tools, not just theoretical concepts. **Abstraction** reduces complexity, **encapsulation** protects data, **inheritance** promotes code reuse, and **polymorphism** boosts flexibility. Keeping these ideas fresh ensures your software stays clean, scalable, and maintainable.
