Understanding C# Polymorphism
Polymorphism in C# is a key concept of object-oriented programming (OOP) that allows methods or objects to take multiple forms. It enables a derived class to override the behavior of a base class, allowing a consistent interface while maintaining flexibility in how behavior is implemented.
Key Topics
- What is Polymorphism?
- Method Overriding
- Virtual Methods
- Abstract Classes and Methods
- Polymorphism in Action
What is Polymorphism?
Polymorphism allows objects of different types to be treated as objects of a common base type. It is achieved primarily through method overriding and the use of virtual and abstract methods.
Example: Basic Polymorphism
public class Animal
{
public virtual void Speak()
{
Console.WriteLine("The animal makes a sound.");
}
}
public class Dog : Animal
{
public override void Speak()
{
Console.WriteLine("The dog barks.");
}
}
public class Cat : Animal
{
public override void Speak()
{
Console.WriteLine("The cat meows.");
}
}
class Program
{
static void Main(string[] args)
{
// Polymorphism: base class reference to derived objects
Animal myDog = new Dog();
Animal myCat = new Cat();
// Calls the overridden methods
myDog.Speak(); // Output: The dog barks.
myCat.Speak(); // Output: The cat meows.
}
}
Output:
The dog barks. The cat meows.
Explanation: Polymorphism allows us to use a base class reference (in this case, Animal
) to call methods on derived class objects (Dog
and Cat
). Each derived class overrides the Speak()
method to provide its specific behavior.
Method Overriding
Method overriding in C# allows a derived class to provide a specific implementation of a method that is already defined in its base class. To override a method, the base method must be marked with the virtual
keyword, and the derived class method must be marked with the override
keyword.
Example: Method Overriding
public class Vehicle
{
// Virtual method in base class
public virtual void StartEngine()
{
Console.WriteLine("Starting engine...");
}
}
public class Car : Vehicle
{
// Override method in derived class
public override void StartEngine()
{
Console.WriteLine("Starting car engine...");
}
}
public class Motorcycle : Vehicle
{
// Override method in derived class
public override void StartEngine()
{
Console.WriteLine("Starting motorcycle engine...");
}
}
class Program
{
static void Main(string[] args)
{
Vehicle car = new Car();
Vehicle motorcycle = new Motorcycle();
// Calls the overridden method
car.StartEngine(); // Output: Starting car engine...
motorcycle.StartEngine(); // Output: Starting motorcycle engine...
}
}
Output:
Starting car engine... Starting motorcycle engine...
Explanation: Method overriding allows derived classes (Car
and Motorcycle
) to provide their own implementations of the StartEngine()
method, which is originally defined in the base class Vehicle
.
Virtual Methods
A virtual
method in a base class provides the ability for derived classes to override the method's implementation. Virtual methods are the foundation of polymorphism in C#.
Example: Using Virtual Methods
public class Employee
{
// Virtual method
public virtual void Work()
{
Console.WriteLine("Employee is working...");
}
}
public class Manager : Employee
{
// Override the virtual method
public override void Work()
{
Console.WriteLine("Manager is overseeing the project...");
}
}
class Program
{
static void Main(string[] args)
{
Employee employee = new Employee();
Employee manager = new Manager();
// Call the Work method
employee.Work(); // Output: Employee is working...
manager.Work(); // Output: Manager is overseeing the project...
}
}
Output:
Employee is working... Manager is overseeing the project...
Explanation: In this example, the base class Employee
defines a virtual method Work()
. The derived class Manager
overrides this method to provide specific behavior. The base class reference can call the overridden method in the derived class.
Abstract Classes and Methods
Abstract classes in C# are base classes that cannot be instantiated and often contain abstract methods, which are methods without a body. Derived classes are required to provide implementations for all abstract methods.
Example: Using Abstract Classes and Methods
public abstract class Shape
{
// Abstract method (no implementation)
public abstract double CalculateArea();
}
public class Circle : Shape
{
public double Radius { get; set; }
// Implement the abstract method
public override double CalculateArea()
{
return Math.PI * Radius * Radius;
}
}
class Program
{
static void Main(string[] args)
{
// Create a new Circle object
Circle circle = new Circle { Radius = 5 };
// Calculate and display the area
Console.WriteLine($"Circle Area: {circle.CalculateArea()}");
}
}
Output:
Circle Area: 78.53981633974483
Explanation: The abstract class Shape
contains the abstract method CalculateArea()
, which is implemented in the derived class Circle
. The abstract method enforces that any class inheriting from Shape
must provide its own implementation of CalculateArea()
.
Polymorphism in Action
Polymorphism can be seen in action when you use a base class reference to invoke overridden methods in derived class objects. This provides flexibility while keeping the code maintainable.
Example: Polymorphism in Action
public class Instrument
{
public virtual void Play()
{
Console.WriteLine("Playing an instrument...");
}
}
public class Piano : Instrument
{
public override void Play()
{
Console.WriteLine("Playing the piano...");
}
}
public class Guitar : Instrument
{
public override void Play()
{
Console.WriteLine("Playing the guitar...");
}
}
class Program
{
static void Main(string[] args)
{
Instrument piano = new Piano();
Instrument guitar = new Guitar();
piano.Play(); // Output: Playing the piano...
guitar.Play(); // Output: Playing the guitar...
}
}
Output:
Playing the piano... Playing the guitar...
Explanation: In this example, the base class Instrument
defines a Play()
method. The derived classes Piano
and Guitar
override this method. Using polymorphism, we invoke the correct implementation of the Play()
method based on the object type at runtime.
Key Takeaways
- Polymorphism allows objects of different derived types to be treated as objects of a common base type.
- Method overriding enables derived classes to provide their own implementation of base class methods.
- Virtual methods allow derived classes to override the behavior of base class methods.
- Abstract classes define abstract methods that must be implemented by derived classes.