Перегрузка операторов
Часть раздела Объектно-ориентированное программирование путешествия по C# на Coddy. Урок 36 из 70.
Перегрузка операторов позволяет определить, как такие операторы, как +, - или ==, работают с вашими пользовательскими классами. Вместо вызова таких методов, как point1.Add(point2), можно написать более естественное выражение point1 + point2.
Чтобы перегрузить оператор, создайте специальный статический метод с использованием ключевого слова operator:
public class Vector
{
public int X { get; }
public int Y { get; }
public Vector(int x, int y)
{
X = x;
Y = y;
}
public static Vector operator +(Vector a, Vector b)
{
return new Vector(a.X + b.X, a.Y + b.Y);
}
}Теперь вы можете естественным образом складывать векторы:
Vector v1 = new Vector(3, 4);
Vector v2 = new Vector(1, 2);
Vector v3 = v1 + v2; // X = 4, Y = 6Метод должен быть public static, и по крайней мере один параметр должен иметь содержащий тип. Вы можете перегружать арифметические операторы (+, -, *, /), операторы сравнения (==, !=, <, >) и унарные операторы (-, !, ++).
Обратите внимание, что операторы сравнения необходимо перегружать парами: если вы определяете ==, необходимо также определить !=.
Используй operator overloading, когда это делает твой код более интуитивным, особенно для математических типов, таких как векторы, комплексные числа или деньги. Избегай его, если смысл операции не очевиден сразу.
Задание
ЛегкоДавайте создадим class Fraction, который сделает работу с дробями естественной благодаря перегрузке operator. Вместо вызова таких method, как fraction1.Add(fraction2), вы сможете писать интуитивное выражение fraction1 + fraction2.
Вы организуете свой код в двух файлах:
Fraction.cs: Создайте classFractionв namespaceMath, представляющий дробь с числителем и знаменателем. Ваш fraction должен иметь:- Два доступных только для чтения свойства типа integer:
NumeratorиDenominator - constructor, который accepts числитель и знаменатель (именно в таком порядке)
- Перегруженный
+operator, который складывает две дроби по формуле:(a/b) + (c/d) = (a*d + c*b) / (b*d) - Перегруженный
*operator, который перемножает две дроби:(a/b) * (c/d) = (a*c) / (b*d) - Перегруженный
==operator, который возвращаетtrue, если две дроби равны (для сравнения выполните cross multiplication:a*d == c*b) - Перегруженный
!=operator (требуется при перегрузке==), который возвращает противоположный результат== - method
GetDisplay(), который возвращает fraction в виде строки в формате"{Numerator}/{Denominator}"
- Два доступных только для чтения свойства типа integer:
Program.cs: В вашем основном файле создайте две дроби, используя значения input. Продемонстрируйте работу перегруженных operator, сложив и перемножив дроби, а также проверив, равны ли они. Выведите результаты, чтобы показать естественную работу ваших operator.
Вы получите четыре значения input:
- Числитель первой дроби (целое число)
- Знаменатель первой дроби (целое число)
- Числитель второй дроби (целое число)
- Знаменатель второй дроби (целое число)
Выведите output в следующем формате:
Fraction 1: {GetDisplay()}
Fraction 2: {GetDisplay()}
Sum: {GetDisplay()}
Product: {GetDisplay()}
Are equal: {True/False}Например, если input имеют значения 1, 2, 2 и 4, output должен быть следующим:
Fraction 1: 1/2
Fraction 2: 2/4
Sum: 8/8
Product: 2/8
Are equal: TrueОбратите внимание, что 1/2 и 2/4 распознаются как равные, поскольку 1*4 == 2*2. Сумма и произведение вычисляются без упрощения — для этого challenge это нормально. Вся прелесть в том, насколько естественно теперь можно работать с дробями, используя привычные operator!
Попробуйте сами
using System;
using Math;
class Program
{
public static void Main(string[] args)
{
// Прочитать ввод для первой дроби
int num1 = Convert.ToInt32(Console.ReadLine());
int den1 = Convert.ToInt32(Console.ReadLine());
// Прочитать ввод для второй дроби
int num2 = Convert.ToInt32(Console.ReadLine());
int den2 = Convert.ToInt32(Console.ReadLine());
// TODO: Создать два объекта Fraction, используя входные значения
// TODO: Использовать перегруженный оператор + для сложения дробей
// TODO: Использовать перегруженный оператор * для умножения дробей
// TODO: Использовать перегруженный оператор == для проверки равенства
// TODO: Вывести результат в требуемом формате:
// Дробь 1: {GetDisplay()}
// Дробь 2: {GetDisplay()}
// Сумма: {GetDisplay()}
// Произведение: {GetDisplay()}
// Are equal: {True/False}
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыПространства имен и директивыВведение в классы и объектыКлючевое слово 'this'Методы и параметрыПоля и свойстваКонструкторыИнициализаторы объектовИтоги — Простой калькулятор4Наследование
Основы синтаксиса наследования (:)Ключевое слово 'base'Ключевые слова Virtual и OverrideЗапечатанные классыБазовый класс 'object'Итоги — Иерархия сотрудников7Продвинутые возможности
Перегрузка операторовИндексаторы (this[])Переопределение ToString()Методы расширенияПовторение — Пользовательский список10Паттерны проектирования. Часть 1
Введение в паттерны проектированияПотокобезопасный SingletonПаттерн FactoryПаттерн Observer (События)Паттерн Strategy13Финальные испытания
Платформа для онлайн-обученияКомпонент игрового персонажаСервис аренды транспорта2Свойства и статические члены
Автоматически реализуемые свойстваСвойства только для чтения и записиСтатические поля и методыСтатические классыЧлены в виде выражений5Полиморфизм и интерфейсы
Полиморфизм: компиляция vs выполнениеИнтерфейс vs абстрактный классМножественные интерфейсыЯвные интерфейсыUpcasting и DowncastingИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция вместо наследованияGenerics (классы и методы)Делегаты и событияАтрибуты и рефлексияIDisposable и оператор usingОсновы Dependency Injection11Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн Компоновщик3Архитектура классов
Экземплярные и статические данныеКлючевые слова 'readonly' и 'const'Опорные поляПовторение — Менеджер банковских счетов6Инкапсуляция
Модификаторы доступаСвойства для инкапсуляцииРеализация скрытия данныхПаттерны неизменяемостиИтоги — Записи студентов9Переменное количество аргументов
Ключевое слово 'params'Необязательные параметрыИменованные аргументыПерегрузка методовПотренируйтесь самостоятельно: Онлайн-компилятор C#