- •Тема 6. Основы программирования на языке c#
- •Условная операция
- •Операции checked и unchecked
- •Операция поглощения null
- •Безопасность типов
- •Преобразования типов
- •Неявные преобразования
- •Явные преобразования
- •Проверка равенства объектов
- •Упаковка и распаковка
- •Виртуальный метод Equals()
- •Статический метод Equals()
- •Проверка типов значений на равенство
- •Перегрузка операций
- •Как работают операции
- •Пример перегрузки операции: структура Vector
- •Добавление дополнительных перегрузок
- •Перегрузка операций сравнения
- •Пользовательские приведения
- •Реализация пользовательских приведений
- •Приведение между классами
- •Приведение между базовым и производным классами
- •Упаковывающие и распаковывающие приведения
- •Множественные приведения
Перегрузка операций
В этом разделе рассматривается другой тип членов, которые можно определить в классе и структуре: перегруженные операции.
Перегрузка операций понятие, знакомое разработчикам на C++. Однако, поскольку эта концепция является новой для разработчиков на Java и Visual Basic, мы объясним ее здесь. Разработчики на C++, возможно, предпочтут сразу перейти к главному примеру.
Идея перегрузки операций заключается в том, что вы не всегда ограничиваетесь вызовом методов и свойств объектов. Часто возникает необходимость выполнять сложение величин, их умножение, или же осуществить логические операции, такие как сравнение объектов. Предположим, что имеется определенный класс, представляющий математическую матрицу. В мире математики матрицы можно складывать или перемножать, подобно обычным числам. Поэтому, скорее всего, вы захотите написать код вроде такого:
Matrix а, Ь, с;
// Предположим, что а, b и с уже инициализированы
Matrix d = с * (а + b);
С помощью перегрузки операций компилятору можно сообщить, что делают + и * при, использовании с Matrix, что и позволит записать приведенный выше код. Если вы до сих пор кодировали на языке, который не поддерживал перегрузку операций, то, возможно, решите определить методы, выполняющие такие операции. Результат получится не таким интуитивно понятным и, скорее всего, будет выглядеть примерно так:
Matrix d = с.Multiply(a.Add(b));
Как вы знаете, операции вроде + и * изначально предназначены исключительно для работы с предопределенными типами данных и на то имеется важная причина: компилятор точно знает, что означают операции общего назначения для этих типов данных. Так, например, ему известно, как сложить два значения long или как разделить одно double на другое double, и он может сгенерировать соответствующий код на промежуточном языке. Однако когда вы определяете собственные классы или структуры, то должны предоставить компилятору необходимые сведения: какие методы доступны для вызова, какие поля сохраняются в каждом экземпляре, и т.п. Аналогично, если вы хотите использовать операции с собственными типами, то должны'сообщить компилятору, что эти операции будут означать в контексте данного класса. Сделать это позволяет перегрузка операций.
Еще одно обстоятельство, которое следует подчеркнуть это то, что, говоря об операциях, мы имеем в виду не только арифметические операции. Существуют также операции сравнения: ==, <, >,!=, >= и <=. Рассмотрим, к примеру, конструкцию if (a==b). Для классов эта конструкция по умолчанию сравнит две ссылки на предмет того, указывают ли они на одно и то же место в памяти, вместо того, чтобы проверить, содержат ли экземпляры объектов одинаковые данные. Для класса string это поведение переопределено таким образом, что сравнение строк на самом деле сравнивает их содержимое. Вы можете сделать нечто подобное с собственными классами. По умолчанию для структур операция == вообще ничего не делает. Попытка сравнить две структуры, чтобы узнать, содержат ли они одинаковые значения, приведет к ошибке компиляции, если только вы не перегрузите операцию ==, чтобы сообщить компилятору, как он должен выполнять такое сравнение.
Существует множество ситуаций, в которых возможность перегрузки операций позволяет генерировать лучше читаемый и интуитивно понятный код.
Практически любые математические объекты, такие как координаты, векторы, матрицы, тензоры, функции и т.д. Если вы пишете программу, которая выполняет некоторое математическое или физическое моделирование, то почти наверняка используете классы, представляющие эти объекты.
Графические программы, которые используют математические или связанные с координатами объекты при вычислении позиций на экране.
Класс, представляющий денежные суммы (например, в финансовой программе).
Текстовый процессор или программа анализа текста, использующая классы, которые представляют предложения, высказывания и т.п.; операции могут понадобиться для комбинирования предложений (более сложная версия конкатенации строк).
Однако существует также много типов, для которых перегрузка операций нежелательна. Неосмотрительное применение перегрузки операций порождает код, который гораздо труднее понять. Например, умножение двух объектов DateTime даже концептуально не имеет смысла.
