Polymorphism đ
One Name, Many Forms (It's Easier Than It Sounds!)
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.
- â 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)
đŽ 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!
đģ 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!");
}
}
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
- 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...");
}
override
Child says: "I'll do it my way!"
public override void Play()
{
Console.WriteLine("Playing guitar!");
}
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
đ 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!");
}
}
Animal a = new Animal(); â (Error!)
Animal a = new Dog(); â
(Works!)
Part 5: Interfaces - The "I Can Do This" Promise
đ 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!
}
}
}
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();
}
}
}
Part 8: Let's Practice! đŽ
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:
-
Base Class: Vehicle (abstract)
- Properties: Model, Year
- Abstract Method: CalculateRental()
- Virtual Method: DisplayInfo()
-
Derived: Car
- Property: DailyRate
- Override: CalculateRental()
-
Derived: Motorcycle
- Property: MileageRate
- Override: CalculateRental()
-
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
// ===== VEHICLE RENTAL SYSTEM =====
// This is a real-world vehicle rental system
// It shows polymorphism in action
// Base Vehicle Class
public abstract class Vehicle
{
public string Model { get; set; }
public int Year { get; set; }
public int Days { get; set; }
public Vehicle(string model, int year, int days)
{
Model = model;
Year = year;
Days = days;
}
public abstract decimal CalculateRental();
public virtual void DisplayInfo()
{
Console.WriteLine($"đ {Year} {Model}");
Console.WriteLine($" Days: {Days}");
Console.WriteLine($" Total: ${CalculateRental():F2}");
}
}
// Car - Daily rate rental
public class Car : Vehicle
{
public decimal DailyRate { get; set; }
public Car(string model, int year, int days, decimal rate)
: base(model, year, days)
{
DailyRate = rate;
}
public override decimal CalculateRental()
{
return DailyRate * Days;
}
public override void DisplayInfo()
{
Console.WriteLine($"đ Car: {Year} {Model}");
Console.WriteLine($" Daily Rate: ${DailyRate:F2}");
Console.WriteLine($" Days: {Days}");
Console.WriteLine($" Total: ${CalculateRental():F2}");
}
}
// Motorcycle - Mileage-based rental
public class Motorcycle : Vehicle
{
public decimal MileageRate { get; set; }
public int Miles { get; set; }
public Motorcycle(string model, int year, int days,
decimal rate, int miles)
: base(model, year, days)
{
MileageRate = rate;
Miles = miles;
}
public override decimal CalculateRental()
{
return MileageRate * Miles + 20.00m; // Base fee + mileage
}
public override void DisplayInfo()
{
Console.WriteLine($"đī¸ Motorcycle: {Year} {Model}");
Console.WriteLine($" Mileage Rate: ${MileageRate:F2}/mile");
Console.WriteLine($" Miles: {Miles}");
Console.WriteLine($" Total: ${CalculateRental():F2}");
}
}
// Truck - Weight-based rental
public class Truck : Vehicle
{
public decimal WeightRate { get; set; }
public double Weight { get; set; }
public Truck(string model, int year, int days,
decimal rate, double weight)
: base(model, year, days)
{
WeightRate = rate;
Weight = weight;
}
public override decimal CalculateRental()
{
return WeightRate * (decimal)Weight * Days;
}
public override void DisplayInfo()
{
Console.WriteLine($"đ Truck: {Year} {Model}");
Console.WriteLine($" Weight Rate: ${WeightRate:F2}/ton");
Console.WriteLine($" Weight: {Weight} tons");
Console.WriteLine($" Days: {Days}");
Console.WriteLine($" Total: ${CalculateRental():F2}");
}
}
// Program.cs - Rental System
class Program
{
static void Main()
{
Console.WriteLine("đ VEHICLE RENTAL SYSTEM");
Console.WriteLine("âââââââââââââââââââââââââââââââââââ\n");
// Create different vehicles
Vehicle[] vehicles =
{
new Car("Toyota Camry", 2022, 3, 45.00m),
new Motorcycle("Harley Sportster", 2021, 2, 0.50m, 100),
new Truck("Ford F-150", 2023, 4, 30.00m, 2.5)
};
// Process each vehicle polymorphically
foreach (var vehicle in vehicles)
{
vehicle.DisplayInfo(); // Each shows different info!
Console.WriteLine();
}
// Show polymorphism in action
Console.WriteLine("đ Demonstrating Polymorphism:");
foreach (var vehicle in vehicles)
{
Console.WriteLine($"{vehicle.Model} rental: ${vehicle.CalculateRental():F2}");
}
}
}