Добавить в цитаты Настройки чтения

Страница 57 из 188

Обратная величина числа 5 равна 0.2Дробная часть числа 4.234 равна 0.23410 — четное число.5 — нечетное число.```Обратите внимание на то, что последняя строка приведенной выше программы закомментирована. Класс NumericFn является статическим, и поэтомулюбая попытка создать объект этого класса может привести к ошибке во времякомпиляции. Ошибкой будет также считаться попытка сделать нестатическим членкласса NumericFn.

И последнее замечание: несмотря на то, что для статического класса не допускаетсяналичие конструктора экземпляра, у него может быть статический конструктор.

ГЛАВА 9. Перегрузка операторов

В языке C# допускается определять назначение оператора по отношению к создаваемому классу. Этотпроцесс называется перегрузкой операторов. Благодаря перегрузке расширяется сфера применения операторав классе. При этом действие оператора полностью контролируется и может меняться в зависимости от конкретногокласса. Например, оператор + может использоваться дляввода объекта в связный список в одном классе, где определяется такой список, тогда как в другом классе его назначение может оказаться совершенно иным.

Когда оператор перегружается, ни одно из его первоначальных назначений не теряется. Он просто выполняет ещеодну, новую операцию относительно конкретного объекта.Поэтому перегрузка оператора +, например, для обработки связного списка не меняет его назначение по отношениюк целым числам, т.е. к их сложению.

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

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

Существуют две формы операторных методов (operator): одна — для унарныхоператоров, другая — для бинарных. Ниже приведена общая форма для каждой разновидности этих методов.// Общая форма перегрузки унарного оператора.public static возвращаемый_тип operator op(тип_параметра операнд){ // операции}// Общая форма перегрузки бинарного оператора.public static возвращаемый_тип operator op(тип_параметра1 операнд1,тип_параметра1 операнд2){ // операции}



Здесь вместо ор подставляется перегружаемый оператор, например + или /; а возвращаемый_тип обозначает конкретный тип значения, возвращаемого указанной операцией. Это значение может быть любого типа, но зачастую оно указывается такого жетипа, как и у класса, для которого перегружается оператор. Такая корреляция упрощает применение перегружаемых операторов в выражениях. Для унарных операторовоперанд обозначает передаваемый операнд, а для бинарных операторов то же самоеобозначают операнд1 и операнд2. Обратите внимание на то, что операторные методы должны иметь оба типа, public и static.

Тип операнда унарных операторов должен быть таким же, как и у класса, для которого перегружается оператор. А в бинарных операторах хотя бы один из операндовдолжен быть такого же типа, как и у его класса. Следовательно, в C# не допускаетсяперегрузка любых операторов для объектов, которые еще не были созданы. Например,назначение оператора + нельзя переопределить для элементов типа int или string.И еще одно замечание: в параметрах оператора нельзя использовать модификаторref или out.Перегрузка бинарных операторов

Для того чтобы продемонстрировать принцип действия перегрузки операторов,начнем с простого примера, в котором перегружаются два оператора — + и -. В приведенной ниже программе создается класс ThreeD, содержащий координаты объектав трехмерном пространстве. Перегружаемый оператор + складывает отдельные координаты одного объекта типа ThreeD с координатами другого. А перегружаемый оператор - вычитает координаты одного объекта из координат другого.// Пример перегрузки бинарных операторов.using System;// Класс для хранения трехмерных координат.class ThreeD { int х, у, z; // трехмерные координаты public ThreeD() { х = у = z = 0; } public ThreeD(int i, int j, int k) { x = i; у = j; z = k; } // Перегрузить бинарный оператор +. public static ThreeD operator +(ThreeD op1, ThreeD op2) { ThreeD result = new ThreeD(); /* Сложить координаты двух точек и возвратить результат. */ result.х = op1.x + ор2.х; // Эти операторы выполняют result.у = op1.y + ор2.у; // целочисленное сложение, result.z = op1.z + op2.z; // сохраняя свое исходное назначение. return result; } // Перегрузить бинарный оператор -. public static ThreeD operator -(ThreeD op1, ThreeD op2) { ThreeD result = new ThreeD(); /* Обратите внимание на порядок следования операндов: op1 — левый операнд, а ор2 — правый операнд. */ result.х = op1.x - ор2.х; // Эти операторы result.у = op1.y - ор2.у; // выполняют целочисленное result.z = op1.z - op2.z; // вычитание return result; } // Вывести координаты X, Y, Z. public void Show() { Console.WriteLine(x + ", " + у + ", " + z); }}class ThreeDDemo { static void Main() { ThreeD a = new ThreeD(1, 2, 3); ThreeD b = new ThreeD(10, 10, 10); ThreeD c; Console.Write("Координаты точки a: "); a.Show(); Console.WriteLine(); Console.Write("Координаты точки b: "); b.Show(); Console.WriteLine(); с = а + b; // сложить координаты точек а и b Console.Write("Результат сложения а + b: "); с.Show(); Console.WriteLine(); с = а + b + с; // сложить координаты точек а, b и с Console.Write("Результат сложения а + b + с: "); с.Show(); Console.WriteLine(); с = с - а; // вычесть координаты точки а Console.Write("Результат вычитания с - а: "); с.Show(); Console.WriteLine(); с = с - b; // вычесть координаты точки b Console.Write("Результат вычитания с - b: "); с.Show(); Console.WriteLine(); }}

При выполнении этой программы получается следующий результат.Координаты точки а: 1, 2, 3Координаты точки b: 10, 10, 10Результат сложения а + b: 11, 12, 13Результат сложения а + b + с: 22, 24, 26Результат вычитания с - а: 21, 22, 23Результат вычитания с - b: 11, 12, 13

Внимательно проанализируем приведенную выше программу, начиная с перегружаемого оператора +. Когда оператор + оперирует двумя объектами типа ThreeD, товеличины их соответствующих координат складываются, как показано в объявленииоператорного метода operator+(). Следует, однако, иметь в виду, что этот операторне видоизменяет значения своих операндов, а лишь возвращает новый объект типаThreeD, содержащий результат операции сложения координат. Для того чтобы сталопонятнее, почему операция + не меняет содержимое объектов, выступающих в ролиее операндов, обратимся к примеру обычной операции арифметического сложения:10 + 12. Результат этой операции равен 22, но она не меняет ни число 10, ни число 12.Несмотря на то что ни одно из правил не препятствует перегруженному операторуизменить значение одного из своих операндов, все же лучше, чтобы действия этогооператора соответствовали его обычному назначению.

Обратите внимание на то, что метод operator+() возвращает объект типа ThreeD.Этот метод мог бы возвратить значение любого допустимого в C# типа, но благодарятому что он возвращает объект типа ThreeD, оператор + можно использовать в таких составных выражениях, как a+b+с. В данном случае выражение а+b дает результат типа ThreeD, который можно затем сложить с объектом с того же типа. Если бывыражение а+b давало результат другого типа, то вычислить составное выражениеa+b+с было бы просто невозможно.

Следует также подчеркнуть, что когда отдельные координаты точек складываются воператоре operator+(), то в результате такого сложения получаются целые значения,поскольку отдельные координаты х, у и z представлены целыми величинами. Но самаперегрузка оператора + для объектов типа ThreeD не оказывает никакого влияния наоперацию сложения целых значений, т.е. она не меняет первоначальное назначениеэтого оператора.