Раз уж на примере животных.
С интефрейсами можно сделать так:
interface ISpeaking {
public void Speak();
}
public class Dog: ISpeaking {
public void Speak() => Console.WriteLine("Гав!");
}
public class Cat: ISpeaking {
public void Speak() => Console.WriteLine("Мяу!");
}
public static void Main() {
ISpeaking[] speakers = new ISpeaking[] {new Cat(), new Dog()};
foreach(ISpeaking speaker in speakers)
speaker.Speak();
}
Более применимый пример - интерфейс IEnumerable.
IEnumerable реализуют разные коллекции: массивы, List, HashSet, Dictionary.
С помощью IEnumerable можно пройтись по всем элементам коллекции. Это позволяет избавиться от дублирования кода:
Без интефрейсов:
static void PrintAll(string[] array) {
foreach(var e in array)
Console.WriteLine(e);
}
static void PrintAll(List<string> list) {
foreach(var e in list) { // Дублирование!
Console.WriteLine(e);
}
C интерфейсом:
// Можно использовать и для string[], и для List<string>, и даже для того, о чём мы ещё не знаем!
static void PrintAll(IEnumerable<string> collection) {
foreach(var e in collection) {
Console.WriteLine(e);
}
}
Интерфейсы - это один из способов достичь полиморфизма.