Week 9 - Polymorphism
Table of contents
In this topic, we will learn about polymorphism in C#. Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in C# occurs when a parent class reference is used to refer to a child class object.
Polymorphism
Click to show/hide explanation
Polymorphism is the ability of an object to take on many forms. The most common use of polymorphism in C# occurs when a parent class reference is used to refer to a child class object.
public class Animal
{
public virtual void MakeSound()
{
Console.WriteLine("Grrr");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
}
public class Program
{
public static void Main()
{
Animal unknownAnimal = new Animal();
Animal dog = new Dog();
Animal cat = new Cat();
unknownAnimal.MakeSound(); // Grrr
dog.MakeSound(); // Woof
cat.MakeSound(); // Meow
}
}
Abstract Classes
Click to show/hide explanation
Abstract classes are classes that cannot be instantiated. They can only be inherited from. Abstract classes are declared using the abstract keyword. Abstract classes can contain abstract methods, which are methods that do not have a body. Abstract methods are declared using the abstract keyword and are followed by a semicolon, rather than a body. Abstract methods must be implemented in the child class.
public abstract class Animal
{
public abstract void MakeSound();
public virtual void Eat()
{
Console.WriteLine("Eating some food");
}
}
public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Woof");
}
}
public class Cat : Animal
{
public override void MakeSound()
{
Console.WriteLine("Meow");
}
public override void Eat()
{
// Cats are picky eaters, so they only eat cat food
Console.WriteLine("Eating cat food");
}
}
public class Program
{
public static void Main()
{
Animal dog = new Dog();
Animal cat = new Cat();
dog.MakeSound(); // Woof
cat.MakeSound(); // Meow
dog.Eat(); // Eating some food
cat.Eat(); // Eating cat food
Animal unknownAnimal = new Animal(); // Error: Cannot create an instance of the abstract class or interface 'Animal'
}
}
Interfaces
Click to show/hide explanation
Interfaces are similar to abstract classes, but they cannot contain any implementation. All methods in an interface are abstract by default. Interfaces are declared using the interface keyword. Interfaces can be implemented by classes using the : operator.
public interface IAnimal
{
void MakeSound();
void Eat();
}
public interface IFlyable
{
void Fly();
}
public interface IWalkable
{
void Walk();
}
public interface ISwimmable
{
void Swim();
}
public class Dog : IAnimal, IWalkable
{
public void MakeSound()
{
Console.WriteLine("Woof");
}
public void Eat()
{
Console.WriteLine("Eating some food");
}
public void Walk()
{
Console.WriteLine("Walking");
}
}
public class Dove : IAnimal, IFlyable
{
public void MakeSound()
{
Console.WriteLine("Coo");
}
public void Eat()
{
Console.WriteLine("Eating breadcrumbs");
}
public void Fly()
{
Console.WriteLine("Flying");
}
}
public class Fish : IAnimal, ISwimmable
{
public void MakeSound()
{
Console.WriteLine("Blub");
}
public void Eat()
{
Console.WriteLine("Eating smaller fish");
}
public void Swim()
{
Console.WriteLine("Swimming");
}
}
public class Duck : IAnimal, IFlyable, IWalkable, ISwimmable
{
public void MakeSound()
{
Console.WriteLine("Quack");
}
public void Eat()
{
Console.WriteLine("Eating corn");
}
public void Fly()
{
Console.WriteLine("Flying");
}
public void Walk()
{
Console.WriteLine("Walking");
}
public void Swim()
{
Console.WriteLine("Swimming");
}
}
public class Program
{
public static void Main()
{
Dog dog = new Dog();
Dove dove = new Dove();
Fish fish = new Fish();
Duck duck = new Duck();
// Since all of the classes implement the IAnimal interface, we can use an array of IAnimal to store all of the classes
IAnimal[] animals = new IAnimal[] { dog, dove, fish, duck };
foreach (IAnimal animal in animals)
{
animal.MakeSound(); // Woof, Coo, Blub, Quack
animal.Eat(); // Eating some food, Eating breadcrumbs, Eating smaller fish, Eating corn
// Since animal is an IAnimal, we can't access the methods that are specific to the other interfaces
// animal.Walk(); // Error: 'IAnimal' does not contain a definition for 'Walk'...
// However, we can use the `is` keyword to check if the class implements the interface
if (animal is IWalkable)
{
IWalkable walkableAnimal = (IWalkable)animal;
walkableAnimal.Walk(); // Walking, Walking
}
if (animal is IFlyable)
{
IFlyable flyableAnimal = (IFlyable)animal;
flyableAnimal.Fly(); // Flying
}
if (animal is ISwimmable)
{
ISwimmable swimmableAnimal = (ISwimmable)animal;
swimmableAnimal.Swim(); // Swimming
}
}
// Outside of the foreach loop, we can access the methods that are specific to the other interfaces
dog.Walk(); // Walking
dove.Fly(); // Flying
fish.Swim(); // Swimming
duck.Walk(); // Walking
duck.Fly(); // Flying
duck.Swim(); // Swimming
// Although we can instantiate the IAnimal through the Duck class, this only gives us access to the methods in the IAnimal interface
IAnimal duckByInterface = new Duck();
duckByInterface.MakeSound(); // Quack
duckByInterface.Eat(); // Eating corn
// duckByInterface.Walk(); // Error: 'IAnimal' does not contain a definition for 'Walk'...
// duckByInterface.Fly(); // Error: 'IAnimal' does not contain a definition for 'Fly'...
// duckByInterface.Swim(); // Error: 'IAnimal' does not contain a definition for 'Swim'...
// We can use the `as` keyword to cast the IAnimal to the Duck class
Duck duckByClass = duckByInterface as Duck;
duckByClass.MakeSound(); // Quack
duckByClass.Eat(); // Eating corn
duckByClass.Walk(); // Walking
duckByClass.Fly(); // Flying
duckByClass.Swim(); // Swimming
}
}