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

1. Полиморфизм с наследованием:

Полиморфизм обычно достигается за счет наследования, когда производные классы могут использоваться как экземпляры их базового класса. Это обеспечивает согласованный интерфейс для объектов разных типов. Проиллюстрируем это на примере:

using System;

// Base class representing a Shape
class Shape
{
    public virtual void Draw()
    {
        Console.WriteLine("Drawing a shape.");
    }
}

// Derived classes Circle and Rectangle inheriting from Shape
class Circle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a circle.");
    }
}

class Rectangle : Shape
{
    public override void Draw()
    {
        Console.WriteLine("Drawing a rectangle.");
    }
}

class Program
{
    static void Main()
    {
        Shape shape1 = new Circle();
        Shape shape2 = new Rectangle();

        shape1.Draw(); // Output: Drawing a circle.
        shape2.Draw(); // Output: Drawing a rectangle.
    }
}

В этом примере у нас есть базовый класс Shape с виртуальным методом Draw(), который затем переопределяется классами Circle и Rectangle. Метод Draw() вызывается для объектов базового типа Shape и выполняет соответствующий переопределенный метод из производных классов в зависимости от типа объекта во время выполнения. Это известно как динамический полиморфизм или полиморфизм времени выполнения.

2. Полиморфизм с интерфейсами:

Интерфейсы также играют решающую роль в достижении полиморфизма, предоставляя контракт, который могут реализовать несколько классов. Давайте рассмотрим пример с интерфейсами:

using System;

// Interface representing a Printable object
public interface IPrintable
{
    void Print();
}

// Classes Document and Image implementing IPrintable
class Document : IPrintable
{
    public void Print()
    {
        Console.WriteLine("Printing a document.");
    }
}

class Image : IPrintable
{
    public void Print()
    {
        Console.WriteLine("Printing an image.");
    }
}

class Program
{
    static void Main()
    {
        IPrintable printable1 = new Document();
        IPrintable printable2 = new Image();

        printable1.Print(); // Output: Printing a document.
        printable2.Print(); // Output: Printing an image.
    }
}

В этом примере у нас есть интерфейс IPrintable с методом Print(), который реализован классами Document и Image. Мы создаем экземпляры этих классов и сохраняем их в переменных типа IPrintable. Когда мы вызываем метод Print() для этих переменных, он выполняет соответствующую реализацию, предоставленную конкретными классами.

3. Полиморфизм с перегрузкой метода:

Полиморфизм также может быть достигнут за счет перегрузки методов, когда определяются несколько методов с одинаковыми именами, но разными параметрами. Давайте посмотрим на пример:

using System;

class MathOperations
{
    public int Add(int num1, int num2)
    {
        return num1 + num2;
    }

    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }
}

class Program
{
    static void Main()
    {
        MathOperations math = new MathOperations();
        int result1 = math.Add(5, 10); // Output: 15
        double result2 = math.Add(3.5, 2.5); // Output: 6.0

        Console.WriteLine("Result 1: " + result1);
        Console.WriteLine("Result 2: " + result2);
    }
}

В этом примере класс MathOperations определяет два метода с одинаковым именем Add, но разными типами параметров (целые и двойные). Когда мы вызываем метод Add с разными типами параметров, соответствующий перегруженный метод вызывается на основе типов данных аргументов. Это известно как полиморфизм времени компиляции или статический полиморфизм.

Заключение. Полиморфизм — это мощная концепция, обеспечивающая повторное использование кода, гибкость и расширяемость в объектно-ориентированном программировании. Используя наследование, интерфейсы и перегрузку методов, C# позволяет разработчикам писать чистый, модульный и простой в сопровождении код. Понимание и эффективное использование полиморфизма может привести к созданию надежных и масштабируемых приложений.