Что такое перегрузка операторов
hard

Что такое перегрузка операторов

Для тех, кто пытался, но не понял.

В статье про С++ мы упоминали перегрузку операторов. Это мощный и гибкий инструмент, который может оказаться опасным и непредсказуемым в неумелых руках. Настало время разобраться.

👉 Опытным программистам: мы намеренно упростим детали для понимания сути. Ну сорян.

На примере сложения

Во всех языках есть оператор «плюс» — обычно он умеет складывать числа и соединять строки:

2 + 2 = 4

2.2 + 1.8 = 4.0

−2 + 2 = 0

−2 + 0 = –2

−2 + −2 = −4

‘2’ + ‘2’ = ‘22’

‘два’ + ‘два’ = ‘двадва’

‘четы’ + ‘ре’ = ‘четыре’

Допустим, мы пишем софт для интернет-магазина, и у нас есть там класс объектов «заказ». Напомним, что класс — это как бы чертёж, по которому создаются объекты. А объект — это такая коробка с данными и функциями, которыми мы можем управлять как единым целым. Подробнее об этом — в статьях про объекты и классы.

В объекте типа «заказ» лежит куча всего:

  • массив с содержимым корзины,
  • дата и время, когда сформирован заказ,
  • метод «очистить корзину»,
  • место для промокода,
  • метод «применить промокод»,
  • метод «проверить наличие товаров по складу»
  • идентификатор пользователя,
  • что-нибудь ещё интересное.

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

  • Если идентификатор постоянный, значит, мы однозначно пользователя узнали (его адрес, номер кредитки и т. д.).
  • Если идентификатор временный, значит, мы не знаем, что за пользователь — просто храним его корзину, пока он не оформит заказ. Это может быть новый человек или старый, но ещё не залогинившийся. В любом случае мы должны хранить его данные.

В какой-то момент пользователь с временным идентификатором логинится в систему, и нам хочется сделать следующую операцию:

zakaz_5058303 + zakaz_user121239

Обе части выражения — это объекты класса «Заказ». А наш язык программирования не знает, что значит «сложить два объекта класса „Заказ“». Он не знает:

  • Что с чем складывать? Число товаров? Суммы? Номера товаров? Номера телефонов? Ведь язык не понимает, что за объект перед ним. Для него это просто коробка с данными, он может с ними делать что хочешь.
  • Что возвращать? Число? Строку? Объект? Список заказов?
  • Может быть, нужно сравнить два заказа и по каким-то критериям определить самый актуальный?
  • Или нужно объединить две корзины в одну?
  • А что тогда делать с повторяющимися товарами? Заменить? Добавить в количество? Проигнорировать?

Вроде бы простая операция — а столько вопросов. Вот этому всему мы можем обучить оператор «+», и это будет перегрузка оператора.

👉 Короче

Перегрузка оператора — это когда мы обучаем язык программирования, как оператору типа плюс, минус, умножить и т. д. вести себя с определённым типом вводных — например, с объектами, матрицами или картинками.

В случае с нашим примером мы можем сказать, что если складываются два заказа, делай следующее:

  1. Найди, какой из этих заказов постоянный.
  2. Переложи из временного в постоянный все уникальные товары.
  3. Если есть неуникальные товары (например, и в том, и в другом заказе была одна и та же позиция), склей их и поставь максимальное количество. Например, если в постоянном заказе стояло 3 штуки одного артикула, а во временном этого же артикула 9 штук, то поставь в постоянный 9 штук.
  4. Временному заказу поставь статус «Склеено».
  5. Залогируй время склейки заказов.
  6. Верни постоянный заказ с обновлёнными данными.

Довольно много действий для одного плюса, не находите?

Что хорошего в перегрузке

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

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

Чем опасна перегрузка операторов

Когда вы используете в коде перегруженный оператор, он выглядит как самый обычный оператор. Ну складывает и складывает. Ну умножает и умножает, чего такого-то?

Это, с одной стороны, элегантно. А с другой, создаёт проблемы в отладке.

  1. Представьте, что после вас какой-то программист переделал структуру класса «Заказ», и теперь там по-другому работает массив с товарными позициями. Раньше у товаров были числовые идентификаторы типа integer (целые числа), а новый программист переделал их на строки.
  2. Ваш язык в неявном виде поддерживает сравнение чисел со строками и наоборот. Он производит какие-то свои преобразования и позволяет сравнить число со строкой. В 99,9% случаев это не сломает вашу программу, и даже перегруженный оператор будет работать.
  3. Но в 0,1% случаев сравнение случится некорректно, и никто не будет понимать, в чём дело. Где-то под капотом перегруженный оператор некорректно склеивает списки покупок, у пользователя вываливаются какие-то «левые» товары, которых он не заказывал. Он не глядя их оплачивает и потом катает жалобу на ваш магазин.

А ещё, в особо экзотических случаях и больших проектах, программист шутки ради может перегрузить оператор сложения так, что он будет не складывать, а вычитать. И заметить, в чём тут ошибка, в таких случаях бывает очень сложно.

И что?

Перегрузка операторов — это полезно, но сложно.

Если программист не понимает полностью механизма работы перегрузок, лучше не перегружать.

Если понимает — он молодец и может учить стандартные инструменты нестандартному поведению.

Не перегружайтесь, берегите себя.

Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Блогеры и колёса

Эту задачу могут решить только люди с абстрактным мышлением

easy
Делаем страницу «О себе» на Бутстрапе

Если ты можешь сделать страницу о себе, ты можешь сделать всё.

medium
Делаем собственный таймер для спорта
Делаем собственный таймер для спорта

Без рекламы и встроенных покупок.

hard
Как работает BitTorrent и почему пиратские торренты так сложно заблокировать
Как работает BitTorrent и почему пиратские торренты так сложно заблокировать

Конспект подкаста «Запуск завтра»

easy
Почему второй язык программирования выучить проще, чем первый?
Почему второй язык программирования выучить проще, чем первый?

Секрет — в знании алгоритмов, а не синтаксиса

easy
Где брать данные для анализа и машинного обучения: бесплатно и удобно
Где брать данные для анализа и машинного обучения: бесплатно и удобно

Подойдут для аналитики и data-science

easy
Зачем нужны базы данных
Зачем нужны базы данных

И какие они бывают.

easy
Что такое куки

8 вопросов, которые вы всегда хотели задать, но боялись куки.

easy
Специалист техподдержки: что делает и сколько зарабатывает
Специалист техподдержки: что делает и сколько зарабатывает

И как им стать

easy
hard