Я разрабатываю статически и строго типизированный, скомпилированный язык, и я возвращаюсь к мысли о том, включать ли перегрузку функций как функцию языка. Я понял, что я немного предвзят, исходя в основном из C[++|#]
фона.
Каковы наиболее убедительные аргументы за и против включения перегрузки функций в языке?
РЕДАКТИРОВАТЬ: нет никого, кто имеет противоположное мнение?
Бертран Мейер (создатель Eiffel в 1985/1986) вызывает метод, перегружающий это: (источник)
механизм тщеславия, который ничего не привносит в семантическую силу языка ОО, но затрудняет читабельность и усложняет задачу каждого
Теперь это некоторые обширные обобщения, но он умный парень, поэтому я могу с уверенностью сказать, что он может их поддержать, если понадобится. Фактически, он почти убедил Брэда Абрамса (одного из разработчиков CLSv1), что .NET не должен поддерживать перегрузку методов. (источник) Это очень мощный материал. Может ли кто-нибудь пролить свет на его мысли, и оправдана ли его точка зрения еще 25 лет спустя?
источник
Я рекомендую хотя бы знать классы типов в Haskell. Классы типов были созданы для дисциплинированного подхода к перегрузке операторов, но нашли другое применение и в некоторой степени сделали Haskell тем, чем он является.
Например, вот пример специальной перегрузки (не совсем допустимый Haskell):
И вот тот же пример перегрузки классами типов:
Недостаток этого является то, что вы должны придумать забавные имена для всех классов типов (например , в Haskell, у вас есть довольно абстрактно
Monad
,Functor
,Applicative
а также более простой и узнаваемыйEq
,Num
иOrd
).Плюс в том, что, как только вы познакомитесь с классом типов, вы знаете, как использовать любой тип в этом классе. Кроме того, легко защитить функции от типов, которые не реализуют необходимые классы, например:
Редактировать: В Haskell, если вам нужен
==
оператор, который принимает два разных типа, вы можете использовать класс с несколькими параметрами:Конечно, это, вероятно, плохая идея, поскольку она позволяет явно сравнивать яблоки и апельсины. Тем не менее, вы, возможно, захотите рассмотреть это
+
, поскольку добавлениеWord8
кInt
действительно разумной вещи в некоторых контекстах.источник
(==) :: Int -> Float -> Bool
где-нибудь? (независимо от того, является ли это хорошей идеей, конечно)class Eq a ...
преобразовано в псевдо-C-семействоinterface Eq<A> {bool operator==(A x, A y);}
, и вместо использования шаблонного кода для сравнения произвольных объектов, вы используете этот «интерфейс». Это правильно?==
находиться в другом пространстве имен, но не позволяет его переопределить. Обратите внимание, чтоPrelude
по умолчанию имеется одно пространство имен ( ), но вы можете запретить его загрузку с помощью расширений или явногоimport Prelude ()
импорта (ничего не импортируетсяPrelude
иimport qualified Prelude as P
не будет вставлять символы в текущее пространство имен).Разрешить перегрузку функций, вы не можете делать следующее с необязательными параметрами (или, если можете, не очень).
тривиальный пример не предполагает никакого
base.ToString()
методаисточник
Я всегда предпочитал параметры по умолчанию над перегрузкой функций. Перегруженные функции обычно просто вызывают версию «по умолчанию» с параметрами по умолчанию. Зачем писать
Когда я мог сделать:
Тем не менее, я понимаю, что иногда перегруженные функции делают разные вещи, а не просто вызывают другой вариант с параметрами по умолчанию ... но в таком случае это не плохая идея (на самом деле, это, вероятно, хорошая идея), просто дать ему другое имя.
(Кроме того, аргументы ключевых слов в стиле Python отлично работают с параметрами по умолчанию.)
источник
Array Slice(int start, int length) {...}
перегрузкиArray Slice(int start) {return this.Slice(start, this.Count - start);}
? Это не может быть закодировано с использованием параметров по умолчанию. Как вы думаете, им следует дать разные имена? Если так, как бы вы назвали их?indexOf(char ch)
+indexOf(Date dt)
в списке. Мне тоже нравятся значения по умолчанию, но они не взаимозаменяемы со статической типизацией.Вы только что описали Java. Или C #.
Почему ты изобретаешь колесо?
Убедитесь, что возвращаемый тип является частью сигнатуры метода иперегрузки для вашего сердца, он действительно очищает код, когда вам не нужно говорить.источник
EnumX.Flag1 | Flag2 | Flag3
. Я не буду реализовывать это, хотя. Если бы я это сделал и тип возвращаемого значения не использовался, я бы искал тип возвращаемого значенияvoid
.Grrr .. недостаточно прав, чтобы комментировать еще ..
@ Мейсон Уилер: Знайте тогда об Аде, которая перегружает тип возвращаемого значения. Кроме того, мой язык Феликс делает это тоже в некоторых контекстах, в частности, когда функция возвращает другую функцию, и есть такой вызов:
тип b может использоваться для разрешения перегрузки. Также C ++ перегружает возвращаемый тип в некоторых случаях:
На самом деле существуют алгоритмы перегрузки для возвращаемого типа, использующие вывод типа. Это на самом деле не так сложно сделать с машиной, проблема в том, что людям трудно. (Я думаю, что схема дана в Книге Дракона, если я правильно помню, алгоритм называется алгоритмом качки).
источник
Вариант использования против реализации перегрузки функций: 25 методов с одинаковыми именами, которые делают одно и то же, но с совершенно разными наборами аргументов в самых разных шаблонах.
Вариант использования против невыполнения перегрузки функций: 5 методов с одинаковыми именами с очень похожими наборами типов в одном шаблоне.
В конце концов, я не собираюсь читать документы для API, созданного в обоих случаях.
Но в одном случае речь идет о том, что могут делать пользователи. В другом случае это то, что пользователи должны делать из-за языкового ограничения. ИМО, лучше хотя бы учесть, что авторы программ достаточно умны, чтобы разумно перегружать их, не создавая двусмысленности. Когда вы хлопаете в ладоши и забираете опцию, вы в основном гарантируете двусмысленность. Я больше доверяю пользователям делать правильные вещи, чем предполагать, что они всегда будут делать неправильные вещи. По моему опыту, протекционизм ведет к еще худшему поведению со стороны языкового сообщества.
источник
Я решил предоставить обычные классы перегрузки и многотипных типов на своем языке Felix.
Я считаю (открытую) перегрузку необходимой, особенно в языке с большим количеством числовых типов (у Феликса есть все числовые типы Си). Однако в отличие от C ++, который злоупотребляет перегрузкой, заставляя шаблоны зависеть от этого, полиморфизм Феликса является параметрическим: вам нужно перегрузить шаблоны в C ++, потому что шаблоны в C ++ плохо спроектированы.
Классы типов также представлены в Феликсе. Для тех, кто знает C ++, но не использует Haskell, игнорируйте тех, кто описывает его как перегрузку. Это не удаленно, как перегрузка, скорее, это как специализация шаблона: вы объявляете шаблон, который не реализуете, а затем предоставляете реализации для конкретных случаев по мере необходимости. Типизация является параметрически полиморфной, реализация осуществляется посредством специальной реализации, но она не предназначена для ограничения: она должна реализовывать предполагаемую семантику.
В Haskell (и C ++) вы не можете указать семантику. В C ++ идея «Concepts» - это попытка приблизить семантику. В Феликсе вы можете аппроксимировать намерение с помощью аксиом, сокращений, лемм и теорем.
Основное и единственное преимущество (открытой) перегрузки в таком принципиальном языке, как Felix, заключается в том, что он облегчает запоминание имен библиотечных функций как для автора программы, так и для рецензента кода.
Основным недостатком перегрузки является сложный алгоритм, необходимый для его реализации. Он также не очень хорошо подходит для вывода типов: хотя оба эти метода не являются полностью исключительными, алгоритм выполнения обоих достаточно сложен, и программист, вероятно, не сможет предсказать результаты.
В C ++ это также проблема, поскольку он имеет неаккуратный алгоритм сопоставления и также поддерживает автоматическое преобразование типов: в Феликсе I «исправил» эту проблему, требуя точного сопоставления и не используя автоматических преобразований типов.
Так что у меня есть выбор: перегрузка или вывод типа. Вывод - это мило, но его также очень сложно реализовать таким образом, чтобы правильно диагностировать конфликты. Ocaml, например, сообщает вам, где он обнаруживает конфликт, а не откуда он вывел ожидаемый тип.
Перегрузка не намного лучше, даже если у вас есть качественный компилятор, который пытается сказать вам все кандидаты, может быть трудно прочитать, если кандидаты полиморфны, и еще хуже, если это хакерство шаблона C ++.
источник
Все сводится к контексту, но я думаю, что перегрузка делает класс намного более полезным, когда я использую один, написанный кем-то другим. Вы часто в конечном итоге с меньшей избыточностью.
источник
Если вы ищете пользователей, знакомых с языками семейства C, то да, вам следует, потому что ваши пользователи будут ожидать этого.
источник