Урок 8. Перегрузка базовых операторов C#
На восьмом уроке учебника по объектно-ориентированному программированию на языке C# описывается третий метод перегрузки. Перегружая функциональность операторов, можно определить работу стандартных операторов, включая + и - для новых классов.
Перегрузка оператора
До сих пор на этих уроках мы создали классы для представления объектов реального мира в комплекте с их соответствующими методами и свойствами. Эти объекты не требовали реализации арифметических операторов, так как этот тип функциональности был неуместен. В этой статье мы создадим класс, который поддерживает арифметические операции с помощью перегрузки операторов.
Перегрузка оператора - это просто процесс добавления функциональности оператора в класс. Это позволяет точно определить, как оператор ведет себя при использовании с вашим классом и другими типами данных. Это может быть стандартное использование, такое как возможность добавления значений двух векторов, более сложная математика для умножения матриц или неарифметические функции, такие как использование оператора + для добавления нового элемента в коллекцию или объединения содержимого двух массивов. Несколько перегруженных версий операторов также могут быть созданы для обеспечения различных функциональных возможностей в соответствии с обрабатываемыми типами данных, аналогично различным сигнатурам перегрузки метода.
В этой статье мы создадим новый класс для представления двумерного вектора со свойствами X и Y. Мы будем использовать этот класс в этой статье и будущих статьях, чтобы продемонстрировать перегрузку операторов. Для начала создайте новое консольное приложение с именем "VectorDemo "и добавьте новый файл класса с именем "Vector". Добавьте следующий код в новый класс, чтобы создать свойства и базовый конструктор:
private int _x, _y; public Vector(int x, int y) { _x = x; _y = y; } public int X { get { return _x; } set { _x = value; } } public int Y { get { return _y; } set { _y = value; } }Перегрузка бинарного оператора
Первый тип рассматриваемого оператора-это двоичный оператор, названный так потому, что для работы с ним требуется два значения. К ним относятся простые арифметические операторы, такие как+, -,*, / и %. Для объявления двоичного оператора используется следующий синтаксис:
public static result-type operator binary-operator ( op-type operand, op-type2 operand2 )Это первоначально кажется довольно сложным объявлением, но на самом деле довольно просто. Объявление начинается с public static, поскольку все операторы должны быть объявлены как таковые. Другие области не разрешены и не являются нестатическими операторами.
Тип результата определяет тип данных или класс, возвращаемый в результате использования оператора. Обычно это будет тот же тип, что и класс, в котором он определяется. Однако это не обязательно так, и вполне допустимо возвращать данные другого типа.
Ключевое слово operator добавляется, чтобы сообщить компилятору, что следующий символ двоичного оператора является оператором, а не обычным методом. Затем этот оператор обработает два параметра операнда, каждый из которых имеет свой тип данных (op-type и op-type2). По крайней мере один из этих операндов должен быть того же типа, что и содержащий его класс.
Создание оператора сложения ( + )
Синтаксис бинарных операторов теперь можно использовать для создания нового оператора сложения для класса Vector. Этот оператор просто сложит элементы X и Y двух векторов вместе и вернет новый вектор, содержащий результат. Добавьте следующее В класс Vector, чтобы обеспечить эту функциональность. Обратите внимание, что вместо корректировки одного из операндов создается новый вектор. Это связано с тем, что операнды являются ссылочными типами, и в этом случае исходные значения не должны обновляться.
public static Vector operator +(Vector v1, Vector v2) { return new Vector(v1.X + v2.X, v1.Y + v2.Y); }Теперь мы можем проверить новый оператор вектора, изменив основной метод программы. Следующая программа создает экземпляры двух векторных объектов, складывает их вместе и выводит значения свойств X и Y результирующего вектора.
static void Main(string[] args) { Vector v1 = new Vector(4, 11); Vector v2 = new Vector(0, 8); Vector v3 = v1 + v2; Console.WriteLine("({0},{1})", v3.X, v3.Y); // "(4,19)" }Создание оператора вычитания ( -)
Сложение является коммутативной операцией. Это означает, что порядок двух операндов может быть изменен без влияния на результат. В случае вычитания это не так, поэтому важно помнить, что первый операнд в объявлении представляет значение слева от оператора, а второй операнд представляет значение справа. Если они используются неправильно, результирующее значение будет неверным. Используя эти знания, мы можем добавить оператор вычитания к классу векторов:
public static Vector operator -(Vector v1, Vector v2) { return new Vector(v1.X - v2.X, v1.Y - v2.Y); }Чтобы протестировать новый оператор, измените метод Main следующим образом и выполните программу.
static void Main(string[] args) { Vector v1 = new Vector(4, 11); Vector v2 = new Vector(0, 8); Vector v3 = v1 - v2; Console.WriteLine("({0},{1})", v3.X, v3.Y); // "(4,3)" }Создание оператора умножения ( * )
Последний двоичный оператор, который будет добавлен в класс Vector, предназначен для умножения. Этот оператор будет использоваться для масштабирования вектора путем умножения свойств X и Y на одно и то же целочисленное значение. Это демонстрирует использование операндов другого типа для класса, в котором они определены.
public static Vector operator *(Vector v1, int scale) { return new Vector(v1.X * scale, v1.Y * scale); }Чтобы проверить оператор умножения, снова настройте основной метод:
static void Main(string[] args) { Vector v1 = new Vector(4, 11); Vector v2 = v1 * 3; Console.WriteLine("({0},{1})", v2.X, v2.Y); // "(12,33)" }В коде оператора для оператора умножения вектор является первым операндом, а целое число-вторым. Это означает, что порядок, используемый в операторе умножения, должен иметь вектор слева от оператора и целое значение справа. Изменение порядка операндов в методе Main приведет к ошибке компилятора.
static void Main(string[] args) { Vector v1 = new Vector(4, 11); Vector v2 = 3 * v1; Console.WriteLine("({0},{1})", v2.X, v2.Y); // не компилируется }Если класс должен поддерживать оба варианта умножения, оба должны быть объявлены в коде. Это обеспечивает преимущество, позволяя порядок операндов изменить базовую функцию. Чтобы обеспечить второй вариант умножения, добавьте следующий код в класс Vector. После этого программа будет выполнена правильно.
public static Vector operator *(int scale, Vector v1) { return new Vector(v1.X * scale, v1.Y * scale); }Составные операторы присваивания
Когда арифметический двоичный оператор объявлен, соответствующий составной оператор присваивания также становится доступным классу. Это можно продемонстрировать, изменив основной метод программы:
Vector v1 = new Vector(4, 11); v1 *= 5; Console.WriteLine("({0},{1})", v1.X, v1.Y); // "(20,55)"Перегрузка унарного оператора
Унарные операторы-это те, которые требуют одного операнда. К ним относятся простые операторы инкремента (++) и декремента ( -- ). Для объявления унарного оператора используется следующий синтаксис:
public static result-type operator unary-operator (op-type operand)Этот синтаксис почти идентичен синтаксису, используемому для бинарных операторов. Разница в том, что объявляется только один операнд. Тип операнда должен совпадать с классом, в котором объявлен оператор.
Создание операторов инкремента и декремента
Используя синтаксис, определенный выше, теперь мы можем добавить операторы инкремента и декремента в класс Vector. Обратите внимание, что для каждого из них существует только одно определение. Невозможно различить префиксную и постфиксную версии оператора, поэтому обе они обеспечивают одинаковую базовую функциональность.
Чтобы объявить эти два оператора, добавьте следующий код в класс Vector. Каждый шаг увеличивает или уменьшает свойства X и Y для векторных объектов.
public static Vector operator ++(Vector v) { v.X++; v.Y++; return v; } public static Vector operator --(Vector v) { v.X--; v.Y--; return v; }Чтобы проверить эти операторы, обновите и выполните метод Main:
static void Main(string[] args) { Vector v1 = new Vector(4, 11); v1++; Console.WriteLine("({0},{1})", v1.X, v1.Y); // "(5,12)" v1--;Console.WriteLine("({0},{1})", v1.X, v1.Y); // "(4,11)" }Создание оператора отрицания
Последний арифметический унарный оператор, который будет рассмотрен в этой статье, - это оператор отрицания. Это унарная версия вычитания, используемая для идентификации отрицательной версии значения. Мы можем добавить этот оператор, используя следующий код:
public static Vector operator -(Vector v) { return new Vector(-v.X, -v.Y); }Чтобы проверить оператор отрицания, обновите метод Main и запустите программу.
static void Main(string[] args) { Vector v1 = new Vector(4, 11); Vector v2 = -v1; Console.WriteLine("({0},{1})", v2.X, v2.Y); // "(-4,-11)" }
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.