Polymorphism 🎭

One Name, Many Forms (It's Easier Than It Sounds!)

Beginner Friendly 25 min read Lesson 7 of 11

Hey There! Ready to Learn Polymorphism? 🎭

Polymorphism sounds like a big fancy word, but it's actually super simple! It just means "many forms" - one thing that can act in different ways.

Quick Question: Have you ever used a remote control that works for different TV brands? You press "Volume Up" and it works on any TV, but each TV does it differently. That's polymorphism!
đŸŽ¯ After this lesson, you'll be able to:
  • ✅ Explain polymorphism like a pro (but in simple words)
  • ✅ Use virtual and override (it's not scary!)
  • ✅ Work with abstract classes and methods
  • ✅ Use interfaces (like contracts)
  • ✅ Build flexible, reusable code

Part 1: What is Polymorphism? (The Easy Way)

In Simple Words: Polymorphism means "many forms". It lets you use one name for many different things.
🎮 The Remote Control Analogy

Imagine you have a universal remote:

  • đŸ“ē Press Volume Up on a Samsung TV → Volume goes up
  • đŸ“ē Press Volume Up on a Sony TV → Volume goes up differently
  • đŸ“ē Press Volume Up on a LG TV → Volume goes up again

Same command (Volume Up), different results depending on the TV!

That's Polymorphism: Same method name, different behavior!
đŸ’ģ Code Time!

Parent Class:

public class Animal
{
    public virtual void MakeSound()
    {
        Console.WriteLine("Some sound");
    }
}

Child Classes:

public class Dog : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("🐕 Woof!");
    }
}

public class Cat : Animal
{
    public override void MakeSound()
    {
        Console.WriteLine("🐱 Meow!");
    }
}
🎉 Same method name (MakeSound), different results!
😂 Fun Joke: Why did the polymorphic function break up with the regular function? Because it wanted to see other forms! (I'll show myself out 😅)

Part 2: The Two Types of Polymorphism

⏰ Type 1: Compile-Time (Static)

What: Happens when the code is compiled

Also called: Method Overloading

public class MathHelper
{
    public int Add(int a, int b)  // Version 1
    {
        return a + b;
    }
    
    public double Add(double a, double b)  // Version 2
    {
        return a + b;
    }
}

Same method name, different parameters

đŸŽ¯ Type 2: Run-Time (Dynamic)

What: Happens when the program runs

Also called: Method Overriding

public class Animal
{
    public virtual void Speak() { }
}

public class Dog : Animal
{
    public override void Speak()  // Changes at runtime
    {
        Console.WriteLine("Woof!");
    }
}

Same method name, different behavior

Remember:
  • Overloading = Same name, different parameters (compile-time)
  • Overriding = Same name, same parameters, different behavior (run-time)

Part 3: Virtual and Override - The Dynamic Duo

virtual

Parent says: "You can change me"

public virtual void Play()
{
    Console.WriteLine("Playing...");
}
Parent gives permission
override

Child says: "I'll do it my way!"

public override void Play()
{
    Console.WriteLine("Playing guitar!");
}
Child changes behavior
Why Do This?
  • ✅ Make different objects act differently
  • ✅ Customize behavior without changing parent
  • ✅ Create flexible, reusable code
Animal a = new Dog();
a.Play();  // "Playing guitar!"
đŸŽ¯ Real Example
public class Shape
{
    public virtual double GetArea() => 0;
}

public class Circle : Shape
{
    public double Radius;
    public override double GetArea() => Math.PI * Radius * Radius;
}

public class Rectangle : Shape
{
    public double Width, Height;
    public override double GetArea() => Width * Height;
}

🎉 Each shape calculates area differently!

Part 4: Abstract Classes - The "Must Follow" Rules

What are Abstract Classes? They're like a contract that says "If you want to be my child, you MUST do these things!"
📝 Abstract Class
public abstract class Animal
{
    // MUST be implemented by children
    public abstract void MakeSound();
    
    // Already implemented
    public void Eat()
    {
        Console.WriteLine("Eating...");
    }
}
✅ Child MUST Implement
public class Dog : Animal
{
    public override void MakeSound()  // ✅ Must do this!
    {
        Console.WriteLine("Woof!");
    }
}
Remember: You CANNOT create an abstract class directly:
Animal a = new Animal(); ❌ (Error!)
Animal a = new Dog(); ✅ (Works!)
😂 Joke: Why did the abstract class break up with the concrete class? Because it couldn't commit to a specific implementation! (Okay, that was a programmer joke 😅)

Part 5: Interfaces - The "I Can Do This" Promise

What are Interfaces? They're like a job description that says "If you want this job, you MUST know these skills!"
📝 Interface
public interface IPlayable
{
    void Play();  // No implementation
    void Stop();   // Just the contract
}

No code, just rules!

✅ Class MUST Implement
public class MusicPlayer : IPlayable
{
    public void Play()  // ✅ Must implement
    {
        Console.WriteLine("đŸŽĩ Playing music");
    }
    
    public void Stop()  // ✅ Must implement
    {
        Console.WriteLine("âšī¸ Music stopped");
    }
}
🤔 Abstract vs Interface
Abstract Class Interface
Can have code No code allowed
Can have fields Only methods & properties
One parent only Many interfaces
"IS A" relationship "CAN DO" relationship
💡 Real Example
public interface IAnimal
{
    void MakeSound();
}

public interface IPet
{
    void Play();
}

// A Dog is an Animal and can be a Pet
public class Dog : IAnimal, IPet
{
    public void MakeSound() => Console.WriteLine("Woof!");
    public void Play() => Console.WriteLine("🐕 Playing fetch!");
}

Part 6: Polymorphism in Action

Let's see how polymorphism works in real code!

// Base class
public class Animal
{
    public string Name { get; set; }
    public Animal(string name) => Name = name;
    public virtual void MakeSound() { }
}

// Children
public class Dog : Animal
{
    public Dog(string name) : base(name) { }
    public override void MakeSound() => 
        Console.WriteLine($"{Name} says: Woof!");
}

public class Cat : Animal
{
    public Cat(string name) : base(name) { }
    public override void MakeSound() => 
        Console.WriteLine($"{Name} says: Meow!");
}

public class Cow : Animal
{
    public Cow(string name) : base(name) { }
    public override void MakeSound() => 
        Console.WriteLine($"{Name} says: Moo!");
}

// Program - Using polymorphism
class Program
{
    static void Main()
    {
        Console.WriteLine("🐾 Polymorphism in Action!\n");
        
        // ✅ All treated as Animal, but each acts differently
        Animal[] animals = 
        {
            new Dog("Rex"),
            new Cat("Whiskers"),
            new Cow("Bessie")
        };
        
        foreach (var animal in animals)
        {
            animal.MakeSound();  // Different sounds!
        }
    }
}
🎉 Output:
Rex says: Woof!
Whiskers says: Meow!
Bessie says: Moo!

✅ Same method call (MakeSound), different results!

Part 7: Real-World Example - Payment System đŸ’ŗ

Let's build a Payment System where different payment methods work differently!

// Base Payment Class
public abstract class Payment
{
    public decimal Amount { get; set; }
    public Payment(decimal amount) => Amount = amount;
    
    public abstract void Process();
    public virtual void Receipt() => 
        Console.WriteLine($"đŸ’ĩ Payment of ${Amount} processed");
}

// Credit Card Payment
public class CreditCardPayment : Payment
{
    public string CardNumber { get; set; }
    public CreditCardPayment(decimal amount, string number) 
        : base(amount) => CardNumber = number;
    
    public override void Process() =>
        Console.WriteLine($"đŸ’ŗ Charging ${Amount} to card ending in {CardNumber[^4..]}");
}
// PayPal Payment
public class PayPalPayment : Payment
{
    public string Email { get; set; }
    public PayPalPayment(decimal amount, string email) 
        : base(amount) => Email = email;
    
    public override void Process() =>
        Console.WriteLine($"đŸ’ŗ PayPal: Sending ${Amount} to {Email}");
}

// Cash Payment
public class CashPayment : Payment
{
    public CashPayment(decimal amount) : base(amount) { }
    public override void Process() =>
        Console.WriteLine($"đŸ’ĩ Accepting ${Amount} in cash");
}

// Program.cs
class Program
{
    static void Main()
    {
        Console.WriteLine("đŸ’ŗ PAYMENT SYSTEM\n");
        
        Payment[] payments = 
        {
            new CreditCardPayment(100.00m, "1234-5678-9012-3456"),
            new PayPalPayment(75.00m, "user@email.com"),
            new CashPayment(50.00m)
        };
        
        foreach (var payment in payments)
        {
            payment.Process();    // Each processes differently!
            payment.Receipt();    // Same but works for all
            Console.WriteLine();
        }
    }
}
😂 Payment Joke: Why did the credit card break up with PayPal? Because it couldn't handle the transaction! (I promise this is my last one... maybe 😅)

Part 8: Let's Practice! 🎮

What You're Building: A Vehicle Rental System for a car rental company!
Different vehicles (Car, Motorcycle, Truck) all have rental calculations but each does it differently.
🚗 About This Application

This is a Vehicle Rental System like:

  • 🚗 Enterprise - Rent cars for business
  • đŸī¸ Zipcar - Rent cars by the hour
  • 🚚 U-Haul - Rent trucks for moving

Each vehicle type has a different rental calculation:

  • ✅ Car: Base rate + daily fee
  • ✅ Motorcycle: Base rate + mileage fee
  • ✅ Truck: Base rate + weight fee
Your Mission:
  1. Base Class: Vehicle (abstract)
    • Properties: Model, Year
    • Abstract Method: CalculateRental()
    • Virtual Method: DisplayInfo()
  2. Derived: Car
    • Property: DailyRate
    • Override: CalculateRental()
  3. Derived: Motorcycle
    • Property: MileageRate
    • Override: CalculateRental()
  4. Derived: Truck
    • Property: WeightRate
    • Override: CalculateRental()
💡 How This Organizes Your Code
  • ✅ Common code (Model, Year) goes in Vehicle
  • ✅ Special code (rates) goes in each child
  • ✅ Different calculations use override
  • ✅ Easy to add new vehicle types later
Result: A flexible rental system that's easy to expand!
đŸŽ¯ Goal: Build a working vehicle rental system using polymorphism - just like real rental companies use!

🎉 What You Learned Today!

Polymorphism
One name, many forms
virtual/override
Change behavior
Abstract
Must-follow rules
Interfaces
I can do this
Overloading
Compile-time
Overriding
Run-time
Real Example
Vehicle Rental! 🚗
Test Your Knowledge - Take Quiz