stringtranslate.com

Перегрузка оператора

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

Обоснование

Перегрузка операторов является синтаксическим сахаром и используется потому, что она позволяет программировать с использованием нотации, более близкой к целевой области [1] , и обеспечивает определяемым пользователем типам тот же уровень синтаксической поддержки, что и типам, встроенным в язык. Это распространено, например, в научных вычислениях, где позволяет манипулировать вычислительными представлениями математических объектов с тем же синтаксисом, что и на бумаге.

Перегрузка операторов не меняет выразительных возможностей языка (с функциями), поскольку ее можно эмулировать с помощью вызовов функций. Например, рассмотрим переменные aнекоторого bопределяемого cпользователем типа, например матрицы :

a + b * c

На языке, поддерживающем перегрузку операторов, и при обычном предположении, что оператор «*» имеет более высокий приоритет , чем оператор «+», это краткий способ записи:

Add(a, Multiply(b, c))

Однако первый синтаксис отражает обычное математическое использование.

Примеры

В этом случае оператор сложения перегружается, чтобы разрешить добавление пользовательского типа Timeв C++ :

Оператор времени + ( const Time & lhs , const Time & rhs ) { Time temp = lhs ; темп . секунды += правая шкала . секунды ; темп . минуты += темп . секунды / 60 ; темп . секунды %= 60 ; темп . минуты += правое час . минуты ; темп . часы += темп . минут / 60 ; темп . минуты %= 60 ; темп . часы += правая шкала . часы ; температура возврата ; }                                      

Сложение является бинарной операцией , что означает, что оно имеет два операнда . В C++ передаваемые аргументы являются операндами, а tempобъект — возвращаемым значением.

Операцию также можно определить как метод класса, заменив ее lhsскрытым thisаргументом; Однако это приводит к тому, что левый операнд будет иметь тип Time:

// "const" прямо перед открывающей фигурной скобкой означает, что |this| не модифицируется. Время Время :: оператор + ( const Time & rhs ) const { Time temp = * this ; // |это| не следует изменять, поэтому сделайте копию. темп . секунды += правая шкала . секунды ; темп . минуты += темп . секунды / 60 ; темп . секунды %= 60 ; темп . минуты += правое час . минуты ; темп . часы += темп . минут / 60 ; темп . минуты %= 60 ; темп . часы += правая шкала . часы ; температура возврата ; }                                     

Обратите внимание, что унарный оператор, определенный как метод класса, не получит видимого аргумента (он работает только с this):

bool Время :: оператор ! () const { возвращаем часы == 0 && минуты == 0 && секунды == 0 ; }               

Оператор «меньше» (<) часто перегружается для сортировки структуры или класса:

class Pair { public : bool оператор < ( const Pair & p ) const { if ( x_ == p . x_ ) { return y_ < p . й_ ; } Верните x_ < p . Икс_ ; }                         личное : int x_ ; интервал y_ ; };    

Как и в предыдущих примерах, в последнем примере перегрузка операторов выполняется внутри класса. В C++ после перегрузки оператора «меньше» (<) для сортировки некоторых классов можно использовать стандартные функции сортировки .

Критика

Перегрузку операторов часто критикуют [2] , поскольку она позволяет программистам переназначать семантику операторов в зависимости от типов их операндов. Например, использование оператора <<в C++ сдвигает биты в переменной на биты, если и имеют целочисленный тип, но если это выходной поток, то приведенный выше код попытается записать в поток. Поскольку перегрузка операторов позволяет первоначальному программисту изменить обычную семантику оператора и застать врасплох последующих программистов, считается хорошей практикой использовать перегрузку операторов с осторожностью (создатели Java решили не использовать эту возможность, [3] хотя и не обязательно по этой причине).a << bababab

Другая, более тонкая проблема с операторами заключается в том, что некоторые математические правила могут быть ошибочно ожидаемы или непреднамеренно приняты. Например, коммутативность + (т.е. что a + b == b + a) не всегда применима; пример этого происходит, когда операнды являются строками, поскольку + обычно перегружается для выполнения конкатенации строк (т.е. "bird" + "song"Gives "birdsong", while "song" + "bird"Gives "songbird"). Типичное противодействие этому аргументу приходит непосредственно из математики: хотя + коммутативен для целых чисел (и, в более общем случае, для любого комплексного числа), он не коммутативен для других «типов» переменных. На практике + даже не всегда ассоциативен , например, со значениями с плавающей запятой из-за ошибок округления. Другой пример: в математике умножение коммутативно для действительных и комплексных чисел, но не коммутативно при умножении матриц .

Каталог

Классификация некоторых распространенных языков программирования производится по тому, могут ли их операторы перегружаться программистом и ограничены ли операторы заранее определенным набором.

Хронология перегрузки операторов

1960-е годы

Спецификация АЛГОЛа 68 допускала перегрузку операторов. [44]

Выдержка из спецификации языка ALGOL 68 (стр. 177), где определены перегруженные операторы ¬, =, ≠ и abs :

10.2.2. Операции с логическими операндамиа) op ∨ = ( bool a, b) bool :( a | true | b );б) op ∧ = ( bool a, b) bool : (a | b | false );в) op ¬ = ( bool a) bool : (a | false | true );d) op = = ( bool a, b) bool :( a∧b ) ∨ ( ¬b∧¬a );д) op ≠ = ( bool a, b) bool : ¬(a=b);е) op  abs = ( bool a) int : (a | 1 | 0);

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

 прио  макс = 9;  op  max = ( int a, b) int : (a>b | a | b); op  ++ = ( ref  int a ) int : ( a +:= 1 );

1980-е годы

Ada поддерживает перегрузку операторов с момента своего создания, после публикации языкового стандарта Ada 83. Однако разработчики языка решили исключить определение новых операторов. Только существующие в языке операторы могут быть перегружены путем определения новых функций с такими идентификаторами, как «+», «*», «&» и т. д. Последующие версии языка (в 1995 и 2005 годах) сохраняют ограничение на перегрузку существующих операторов. .

В C++ перегрузка операторов более совершенна, чем в ALGOL 68 . [45]

1990-е годы

Разработчики языка Java в Sun Microsystems решили отказаться от перегрузки. [46] [47] [48]

Python позволяет перегружать операторы посредством реализации методов со специальными именами. [49] Например, оператор сложения (+) можно перегрузить, реализовав метод obj.__add__(self, other).

Ruby позволяет перегрузку операторов в качестве синтаксического сахара для простых вызовов методов.

Lua позволяет перегрузку операторов в качестве синтаксического сахара для вызовов методов с дополнительной функцией: если первый операнд не определяет этот оператор, будет использоваться метод для второго операнда.

2000-е

Microsoft добавила перегрузку операторов в C# в 2001 году и в Visual Basic .NET в 2003 году.

Scala рассматривает все операторы как методы и, таким образом, допускает перегрузку операторов через прокси.

В Raku определение всех операторов делегировано лексическим функциям, поэтому с помощью определений функций можно перегружать операторы или добавлять новые операторы. Например, функция, определенная в исходном коде Rakudo для увеличения объекта Date с помощью «+», следующая:

мультиинфикс  :<+> ( Date:D  $d , Int:D  $x ) { Date . новое количество дней ( $d . daycount + $x )}

Поскольку использовалось «multi», функция добавляется в список кандидатов на множественную отправку , а «+» перегружается только в том случае, если соблюдаются ограничения типа в сигнатуре функции. Хотя возможность перегрузки включает + , * , >= , постфикс и термин i и т. д., она также позволяет перегружать различные операторы фигурных скобок: " [ x, y ] ", "x [ y ] ", "x { y } » и «x ( y ) ».

Котлин поддерживает перегрузку операторов с момента своего создания.

Смотрите также

Рекомендации

  1. ^ Страуструп, Бьярн . «Перегрузка оператора». Часто задаваемые вопросы по C++ . Архивировано из оригинала 14 августа 2011 года . Проверено 27 августа 2020 г.
  2. ^ Фишер, Чарльз Н. (2008). «Проблемы перегрузки» (PDF) . Университет Висконсина-Мэдисона .
  3. ^ «Больше никакой перегрузки операторов» . Языковая среда Java . Корпорация Оракл .
  4. ^ Могут быть добавлены совершенно новые операторы.
  5. ^ Бинарные функции с символическим именем можно называть инфиксными.
  6. ^ "Предикат оп / 3" .
  7. Хант, Джон (6 декабря 2012 г.). Smalltalk и объектная ориентация: введение. Springer Science & Business Media. ISBN 978-1-4471-0961-7.
  8. ^ «Бертран Мейер: Основные механизмы языка Эйфеля». se.ethz.ch.Проверено 7 апреля 2021 г.
  9. ^ «Операторские функции в F90». www.mathcs.emory.edu . Проверено 7 апреля 2021 г.
  10. ^ Представлено в Фортране 90.
  11. ^ «3. Справочник по языку — документация Futhark 0.19.0» . futhark.readthedocs.io . Проверено 10 октября 2020 г.
  12. Смит, Крис (9 октября 2012 г.). Программирование F# 3.0: комплексное руководство по написанию простого кода для решения сложных проблем. O'Reilly Media, Inc. ISBN 978-1-4493-2604-3.
  13. ^ Введите классы вместо перегрузки.
  14. ^ "Ио-руководство" . iolanguage.org . Проверено 7 апреля 2021 г.
  15. ^ «Операторы».
  16. ^ «Операторы - R в двух словах, 2-е издание [книга]» . www.oreilly.com . Проверено 7 апреля 2021 г.
  17. ^ «Создание операторов».
  18. ^ «Операторы». Экскурсия по Скале .
  19. ^ «Руководство Seed7: Определение структурированного синтаксиса» . seed7.sourceforge.net . Проверено 29 сентября 2020 г.
  20. ^ «Свифт: Продвинутые операторы».
  21. ^ «Почему Go не поддерживает перегрузку методов и операторов?» . Проверено 4 сентября 2011 г.
  22. ^ «Введение». freepascal.org . Проверено 30 сентября 2020 г.
  23. ^ «Перегрузки операторов» . Проверено 28 сентября 2018 г.
  24. ^ «6.6 Перегрузка операторов». Аннотированное справочное руководство по Ada .
  25. ^ Дрейтон, Питер; Альбахари, Бен; Ньюард, Тед (2003). Коротко о C#. O'Reilly Media, Inc. ISBN 978-0-596-00526-9.
  26. ^ «Перегрузка операторов C++».
  27. ^ «Eclipse Ceylon: полиморфизм операторов». ceylon-lang.org . Проверено 7 апреля 2021 г.
  28. ^ «Перегрузка операторов — язык программирования D» . dlang.org . Проверено 10 октября 2020 г.
  29. ^ «Экскурсия по языку дартс». dart.dev . Проверено 30 сентября 2020 г.
  30. ^ «Перегрузка оператора». bourabai.kz . Проверено 7 апреля 2021 г.
  31. ^ «Язык программирования Apache Groovy — Операторы» . groovy-lang.org . Проверено 30 сентября 2020 г.
  32. ^ «Перегрузка оператора». Многообразие . Проверено 7 июня 2020 г.
  33. ^ «Перегрузка оператора». Котлин . Проверено 24 июня 2018 г.
  34. ^ «Учебник по метаметодам». Lua-пользователи Wiki .
  35. ^ «Реализация операторов для вашего класса» . Проверено 1 октября 2013 г.
  36. ^ «Перегрузка оператора». Бесплатное руководство по Паскалю . Проверено 1 декабря 2014 г.
  37. ^ «Перегрузка оператора». Руководство по Делфи . Проверено 1 декабря 2014 г.
  38. ^ «Магические методы PHP, переопределяющие свойства класса» . Архивировано из оригинала 4 марта 2016 года . Проверено 7 апреля 2015 г.
  39. Орвант, Джон (4 ноября 2002 г.). Информатика и программирование на Perl: лучшее из журнала Perl. O'Reilly Media, Inc., стр. 347–. ISBN 978-0-596-00310-4.
  40. ^ «3. Модель данных». Справочник по языку Python .
  41. ^ «Методы». Официальный FAQ по Ruby .
  42. ^ «Перегрузка оператора». Ржавчина на примере .
  43. ^ «Как: определить оператора (Visual Basic)» .
  44. ^ = Барри Дж. Майу «Отчет об алгоритмическом языке АЛГОЛ 68, раздел 10.2.2». Август 1968 года . Проверено 1 апреля 2007 г. {{cite web}}: Проверить |url=значение ( помощь )
  45. ^ Страуструп, Бьярн . «История C++: 1979–1991» (PDF) . п. 12 . Проверено 1 апреля 2007 г.
  46. ^ «Часто задаваемые вопросы, вопрос 6.9: Почему нет перегрузки операторов?». Список часто задаваемых вопросов по comp.lang.java .
  47. ^ "java.sun.com" . Архивировано из оригинала 7 марта 2009 года . Проверено 26 марта 2009 г.
  48. ^ Хольцнер, Стивен (2001). С++: Черная книга . Скоттсдейл, Аризона: Группа Кориолиса. п. 387. ИСБН 1-57610-777-9. Одна из самых приятных особенностей ООП C++ заключается в том, что вы можете перегружать операторы для обработки объектов ваших классов (вы не можете сделать это в некоторых других ООП-ориентированных языках, таких как Java).
  49. ^ «3. Модель данных, имена специальных методов» . Справочник по языку Python .