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