Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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

Обоснование [ редактировать ]

Перегрузка оператора является синтаксическим сахаром и используется потому, что она позволяет программировать с использованием нотации, более близкой к целевой области [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 | не модифицируется. Время  Time :: operator + ( const  Time &  rhs )  const  {  Time  temp  =  * this ;  // | это | не должны быть изменены, поэтому сделайте копию.  темп . секунд  + =  прав . секунды ;  темп . минут  + =  темп . секунд  /  60 ;  темп . секунд  % =  60 ; темп . минут  + =  прав . минут ;  темп . часов  + =  темп . минут  /  60 ;  темп . минут  % =  60 ;  темп . часы  + =  прав . часы ;  возвратная  температура ; }

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

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

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

class  Pair  {  public :  bool  operator < ( const  Pair &  p )  const  {  if  ( x_  ==  p . x_ )  {  return  y_  <  p . y_ ;  }  return  x_  <  p . x_ ;  } частный :  int  x_ ;  int  y_ ; };

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

Критика [ править ]

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

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

Каталог [ править ]

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

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

1960-е [ править ]

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

Выдержка из спецификации языка 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 );г) op = = ( bool a, b) bool :( a∧b) ∨ (¬b∧¬a);д) op ≠ = ( bool a, b) bool : ¬ (a = b);е) op  abs = ( bool a) int : (a | 1 | 0);

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

1980-е [ править ]

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

В C ++ перегрузка операторов более тонкая, чем в АЛГОЛе 68 . [44]

1990-е [ править ]

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

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

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

2000-е [ править ]

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

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

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

мульти  инфикс: <+> ( Дата: D  $ d , Интервал: D  $ x ) { Дата . new-from-daycount ( d . daycount + x )}

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

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

См. Также [ править ]

  • Перегрузка функций
  • Полиморфизм (информатика)
  • Подпрограмма
  • Оператор (программирование)
  • Операторы в C и C ++
  • Мутаторный метод
  • Индексатор (программирование)
  • Свойство (программирование)

Ссылки [ править ]

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