Вместо поддержки перегрузки методов Ruby перезаписывает существующие методы. Кто-нибудь может объяснить, почему язык был разработан таким образом?
146
Перегрузка методов может быть достигнута путем объявления двух методов с одинаковыми именами и разными сигнатурами. Эти разные подписи могут быть
method(int a, int b) vs method(String a, String b)
method(a) vs method(a, b)
Мы не можем добиться перегрузки метода, используя первый способ, потому что в ruby ( динамически типизированный язык ) нет объявления типа данных . Таким образом, единственный способ определить вышеупомянутый методdef(a,b)
При втором варианте может показаться, что мы можем добиться перегрузки метода, но мы не можем. Допустим, у меня есть два метода с разным количеством аргументов,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
Таким образом, ruby должен поддерживать один метод в цепочке поиска методов с уникальным именем.
«Перегрузка» - это термин, который просто не имеет смысла в Ruby. Это в основном является синонимом «статического аргумента на основе отправки», но Рубин не имеет статическую отправку вообще . Итак, причина, по которой Ruby не поддерживает статическую диспетчеризацию на основе аргументов, заключается в том, что она не поддерживает статическую диспетчеризацию, точка. Он не поддерживает статическую диспетчеризацию любого типа , основанную на аргументах или иным образом.
Теперь, если вы не на самом деле конкретно спрашивать о перегрузке, но , может быть , о динамическом аргументе на основе отправки, то ответ: потому что Мацы не реализовали его. Потому что никто не удосужился предложить это. Потому что никто не удосужился реализовать это.
В целом, динамическая диспетчеризация на основе языка в языке с необязательными аргументами и списками аргументов переменной длины очень трудно понять правильно, и еще труднее сделать ее понятной. Даже в языках со статической диспетчеризацией, основанной на аргументах, и без дополнительных аргументов (например, в Java), иногда почти невозможно сказать для простого смертного, какая перегрузка будет выбрана.
В C # вы можете фактически закодировать любую проблему 3-SAT в разрешение перегрузки, что означает, что разрешение перегрузки в C # является NP-сложным.
Теперь попробуйте это с динамической диспетчеризацией, где у вас есть дополнительное измерение времени, которое нужно держать в голове.
Существуют языки, которые динамически распределяются на основе всех аргументов процедуры, в отличие от объектно-ориентированных языков, которые отправляют только по «скрытому» нулевому
self
аргументу. Common Lisp, например, отправляет динамические типы и даже динамические значения всех аргументов. Clojure рассылает произвольную функцию от всех аргументов (что, кстати, чрезвычайно круто и чрезвычайно мощно).Но я не знаю ни одного языка OO с динамической диспетчеризацией на основе аргументов. Мартин Одерски сказал, что он мог бы рассмотреть возможность добавления диспетчеризации на основе аргументов в Scala, но только если он может одновременно устранить перегрузку и быть обратно совместимым как с существующим кодом Scala, который использует перегрузку, так и с Java (особенно он упомянул Swing и AWT). которые разыгрывают очень сложные трюки, выполняющие практически все неприятные темные ситуации с довольно сложными правилами перегрузки Java). У меня были некоторые идеи по поводу добавления рассылки на основе аргументов в Ruby, но я никогда не мог понять, как сделать это обратно совместимым способом.
источник
def method(a, b = true)
не будет работать, поэтому перегрузка методов невозможна». Это не; это просто сложно. Однако я нашел ЭТОТ ответ действительно информативным.Я полагаю, вы ищете возможность сделать это:
Ruby поддерживает это по-другому:
Обычным шаблоном также является передача параметров в виде хэша:
надеюсь, это поможет
источник
Перегрузка методов имеет смысл в языке со статической типизацией, где можно различать аргументы разных типов
а также между разным количеством аргументов
Первое различие не существует в рубине. Ruby использует динамическую типизацию или «типизацию утки». Второе различие может быть обработано аргументами по умолчанию или при работе с аргументами:
источник
Это не отвечает на вопрос, почему в ruby нет перегрузки методов, но сторонние библиотеки могут это предоставить.
Библиотека contract.ru позволяет перегружать. Пример адаптирован из учебника:
Обратите внимание, что это на самом деле более мощно, чем перегрузка Java, потому что вы можете указать соответствующие значения (например,
1
), а не просто типы.Вы увидите снижение производительности при использовании этого, хотя; вам придется запустить тесты, чтобы решить, сколько вы можете терпеть.
источник
Я часто делаю следующую структуру:
Это позволяет пользователю объекта использовать чистый и понятный method_name: метод. Но если он хочет оптимизировать выполнение, он может напрямую вызвать правильный метод.
Кроме того, это делает ваши тесты яснее и лучше.
источник
Уже есть отличные ответы на вопрос, почему сторона вопроса. однако, если кто-то ищет другие решения, обратите внимание на функциональную рубиновую жемчужину, которая вдохновлена возможностями сопоставления с образцом Elixir .
источник