Виды полиморфизма в C#

Полиморфизм – это один из ключевых принципов объектно-ориентированного программирования (ООП), который позволяет использовать один интерфейс для разных типов данных. В языке C# существует два основных вида полиморфизма: статический и динамический.

Статический полиморфизм

Статический полиморфизм в C# реализуется с помощью перегрузки методов (Method Overloading) и перегрузки операторов (Operator Overloading).

Перегрузка методов

Перегрузка методов позволяет объявлять в одном классе несколько методов с одинаковым именем, но разными параметрами (различие в их количестве или типе). Компилятор выбирает нужную версию метода в момент компиляции.

class Calculator
{
    public int Add(int a, int b)
    {
        return a + b;
    }
    
    public double Add(double a, double b)
    {
        return a + b;
    }
}

В данном примере метод Add перегружен: одна версия работает с int, а другая с double.

Перегрузка операторов

Перегрузка операторов позволяет определять собственное поведение стандартных операторов (+, -, *, / и др.) для пользовательских типов данных.

class Complex
{
    public int Real { get; set; }
    public int Imaginary { get; set; }
    
    public Complex(int real, int imaginary)
    {
        Real = real;
        Imaginary = imaginary;
    }
    
    public static Complex operator +(Complex c1, Complex c2)
    {
        return new Complex(c1.Real + c2.Real, c1.Imaginary + c2.Imaginary);
    }
}

В этом примере перегружен оператор +, который теперь работает с объектами Complex.

Динамический полиморфизм

Динамический полиморфизм достигается через виртуальные методы (virtual methods) и интерфейсы (interfaces).

Виртуальные методы и переопределение

Этот механизм позволяет подклассам изменять реализацию методов, определённых в базовом классе.

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

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

Здесь метод MakeSound в классе Dog переопределяет поведение метода из Animal.

Полиморфизм через интерфейсы

Интерфейсы позволяют различным классам реализовывать один и тот же контракт, но с разной реализацией.

interface IShape
{
    void Draw();
}

class Circle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a circle");
    }
}

class Square : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a square");
    }
}

Благодаря интерфейсу IShape мы можем создавать универсальный код, работающий с разными типами объектов.