Является ли метод перегрузки типом полиморфизма? Мне кажется, что это просто дифференциация методов с одинаковыми именами и разными параметрами. Так что stuff(Thing t)
и stuff(Thing t, int n)
это совершенно разные методы в отношении компилятора и среды выполнения.
Это создает иллюзию со стороны вызывающей стороны, что это один и тот же метод, который по-разному действует на разные типы объектов - полиморфизм. Но это только иллюзия, потому что на самом деле stuff(Thing t)
и stuff(Thing t, int n)
это совершенно разные методы.
Является ли перегрузка метода чем-то большим, чем синтаксический сахар? Я что-то пропустил?
Распространенным определением синтаксического сахара является то, что он является чисто локальным . Смысл изменения части кода на «подслащенный» эквивалент или наоборот, включает в себя локальные изменения, которые не влияют на общую структуру программы. И я думаю, что метод перегрузки точно соответствует этому критерию. Давайте посмотрим на пример, чтобы продемонстрировать:
Рассмотрим класс:
class Reader {
public String read(Book b){
// .. translate the book to text
}
public String read(File b){
// .. translate the file to text
}
}
Теперь рассмотрим другой класс, который использует этот класс:
/* might not be the best example */
class FileProcessor {
Reader reader = new Reader();
public void process(File file){
String text = reader.read(file);
// .. do stuff with the text
}
}
Ладно. Теперь давайте посмотрим, что нужно изменить, если мы заменим перегрузку метода обычными методами:
Эти read
методы в Reader
смену readBook(Book)
и readFile(file)
. Только вопрос изменения их имен.
Код вызова FileProcessor
изменяется незначительно: reader.read(file)
изменяется на reader.readFile(file)
.
Вот и все.
Как видите, разница между использованием перегрузки метода и неиспользованием его носит чисто локальный характер . И именно поэтому я думаю, что это квалифицируется как чистый синтаксический сахар.
Я хотел бы услышать ваши возражения, если у вас есть, может быть, я что-то упустил.
источник
Ответы:
Чтобы ответить на это, сначала нужно определить «синтаксический сахар». Я пойду с Википедией :
Таким образом, согласно этому определению, такие функции, как varargs Java или простое понимание Scala, являются синтаксическим сахаром: они переводят в базовые языковые функции (массив в первом случае, вызовы map / flatmap / filter во втором), и удаление их будет не меняйте то, что вы можете сделать с языком.
Перегрузка методов, однако, не является синтаксическим сахаром в этом определении, потому что удаление его в корне изменит язык (вы больше не сможете отправлять сообщения с другим поведением, основанным на аргументах).
Правда, вы можете имитировать перегрузку метода, если у вас есть какой-то способ доступа к аргументам метода, и вы можете использовать конструкцию «если», основанную на заданных вами аргументах. Но если вы считаете, что синтаксический сахар, вы должны рассмотреть все, что выше машины Тьюринга, чтобы быть синтаксическим сахаром.
источник
sum(numbersArray)
аsum(numbersList)
неsumArray(numbersArray)
иsumList(numbersList)
. Я согласен с Довалем, это похоже на простой синтетический сахар.instanceof
, классы, наследование, интерфейсы, дженерики, отражение или спецификаторов доступа , используяif
,while
, и логические операторы, с точно такой же семантикой . Нет угловых случаев. Обратите внимание, что я не призываю вас вычислять те же вещи, что и конкретные применения этих конструкций. Я уже знаю, что вы можете вычислить все, что угодно, используя логическую логику и ветвления / циклы. Я прошу вас реализовать точные копии семантики этих языковых функций, включая любые статические гарантии, которые они предоставляют (проверки во время компиляции должны выполняться во время компиляции.)Термин синтаксический сахар обычно относится к случаям, когда признак определяется заменой. Язык не определяет, что делает функция, а определяет, что она в точности эквивалентна чему-то другому. Так, например, для каждого цикла
становится:
Или возьмите функцию с переменными аргументами:
Который становится:
Таким образом, существует тривиальная замена синтаксиса для реализации функции с точки зрения других функций.
Давайте посмотрим на перегрузку метода.
Это может быть переписано как:
Но это не эквивалентно этому. В модели Java это нечто иное.
foo(int a)
не реализуетfoo_int
функцию, которая будет создана. Java не реализует перегрузку методов, давая неоднозначные функции забавные имена. Чтобы считаться синтаксическим сахаром, java должен был притворяться, что вы действительно написалиfoo_int
иfoo_double
работаете, но это не так.источник
But, the transformation isn't trivial. At the least, you have to determine the types of the parameters.
очень схематичным, потому что типы не нужно определять ; они известны во время компиляции.foo(int)
/foo(double)
иfoo_int
/foo_double
? Я не очень хорошо знаю Java, но я бы предположил, что такое переименование действительно происходит в JVM (ну, возможно, с использованиемfoo(args)
скорее, чемfoo_args
это происходит - по крайней мере, в C ++ с манипулированием символами (хорошо - маниглинг символов - технически деталь реализации, а не часть). языка).for
циклом не более выразительна, чем Java без него. (Я бы поспорил, что это лучше, лаконичнее, удобочитаемее и лучше вокруг, но не более выразительно.) Однако я не уверен насчет случая перегрузки. Вероятно, мне придется перечитать статью, чтобы быть уверенным. Моя кишка говорит, что это синтаксический сахар, но я не уверен.Учитывая, что искажение имен работает, разве это не должно быть ничем иным, как синтаксическим сахаром?
Это позволяет вызывающему абоненту вообразить, что он вызывает ту же функцию, когда это не так. Но он мог знать настоящие имена всех своих функций. Только если бы удалось достичь отложенного полиморфизма путем передачи нетипизированной переменной в типизированную функцию и установить ее тип так, чтобы при вызове можно было перейти к правильной версии в соответствии с именем, это было бы истинным языковым свойством.
К сожалению, я никогда не видел, чтобы язык делал это. Когда возникает двусмысленность, эти компиляторы не разрешают ее, а настаивают, чтобы автор разрешил ее за них.
источник
dynamic
то перегрузка разрешение происходит во время выполнения, а не во время компиляции . Вот что такое множественная диспетчеризация, и она не может быть реплицирована переименованием функций.В зависимости от языка, это синтаксический сахар или нет.
Например, в C ++ вы можете делать вещи, используя перегрузку и шаблоны, что было бы невозможно без сложностей (запишите вручную все экземпляры шаблона или добавьте много параметров шаблона).
Обратите внимание, что динамическая диспетчеризация - это форма перегрузки, динамически разрешаемая по некоторым параметрам (для некоторых языков только специальный, этот , но не все языки настолько ограничены), и я бы не назвал эту форму перегрузки синтаксическим сахаром.
источник
Для современных языков это просто синтаксический сахар; в совершенно не зависящем от языка виде, это нечто большее.
Ранее в этом ответе просто говорилось, что это больше, чем синтаксический сахар, но, если вы увидите в комментариях, Фалько поднял вопрос о том, что есть одна часть загадки, которая, по-видимому, отсутствует во всех современных языках; они не смешивают перегрузку методов с динамическим определением того, какую функцию вызывать на одном шаге. Это будет уточнено позже.
Вот почему это должно быть больше.
Рассмотрим язык, который поддерживает как перегрузку метода, так и нетипизированные переменные. Вы можете иметь следующие прототипы методов:
В некоторых языках вы, вероятно, будете вынуждены знать во время компиляции, какой из них будет вызываться заданной строкой кода. Но в некоторых языках не все переменные типизированы (или все они неявно типизированы как
Object
или что угодно), поэтому представьте себе создание словаря, ключи которого сопоставляются со значениями различных типов:Что же делать, если вы хотите подать заявку
someFunction
на один из этих номеров? Вы называете это:Является ли
someFunction(int)
называется, илиsomeFunction(string)
называется? Здесь вы видите один пример, где это не полностью ортогональные методы, особенно в языках более высокого уровня. Язык должен выяснить - во время выполнения - какой из них вызывать, поэтому он все равно должен рассматривать их как, по крайней мере, один и тот же метод.Почему бы просто не использовать шаблоны? Почему бы просто не использовать нетипизированный аргумент?
Гибкость и более тонкий контроль. Иногда лучше использовать шаблоны / нетипизированные аргументы, но иногда это не так.
Вы должны подумать о случаях, когда, например, у вас может быть две сигнатуры метода, каждая из которых принимает аргументы
int
a и astring
, но порядок в каждой сигнатуре различен. У вас вполне может быть веская причина для этого, так как реализация каждой подписи может делать в основном одно и то же, но только с немного другим поворотом; регистрация может быть другой, например. Или даже если они делают одну и ту же вещь, вы можете автоматически получать определенную информацию только из того порядка, в котором были указаны аргументы. Технически вы могли бы просто использовать операторы псевдопереключателя, чтобы определить тип каждого из переданных аргументов, но это может привести к путанице.Так что это следующий пример плохой практики программирования?
Да по большому счету. В этом конкретном примере это может помешать кому-то попытаться применить это к определенным примитивным типам и получить неожиданное поведение (что может быть хорошо); но давайте просто предположим, что я сократил приведенный выше код и что у вас фактически есть перегрузки для всех примитивных типов, а также для
Object
s. Тогда следующий фрагмент кода действительно более уместен:Но что, если вам нужно использовать это только для
int
s иstring
s, и что, если вы хотите, чтобы он возвращал true, основываясь на более простых или более сложных условиях соответственно? Тогда у вас есть веская причина использовать перегрузку:Но почему бы просто не дать этим функциям два разных имени? Вы все еще обладаете таким же количеством мелкозернистого контроля, не так ли?
Потому что, как указывалось ранее, некоторые отели используют цифры, некоторые используют буквы, а некоторые используют комбинацию цифр и букв:
Это все еще не совсем тот код, который я использовал бы в реальной жизни, но он должен проиллюстрировать то, что я делаю просто отлично.
Но ... Вот почему это не более чем синтаксический сахар в современных языках.
Falco поднял вопрос в комментариях о том, что современные языки в основном не смешивают перегрузку методов и динамический выбор функций в пределах одного шага. Ранее я понимал, что некоторые языки работают, так как вы могли перегрузить
appearsToBeFirstFloor
в приведенном выше примере, а затем язык во время выполнения будет определять, какую версию функции вызывать, в зависимости от значения времени выполнения нетипизированной переменной. Эта путаница частично возникла из-за работы с языками ECMA-типов, такими как ActionScript 3.0, в которых вы можете легко рандомизировать, какая функция вызывается для определенной строки кода во время выполнения.Как вы, возможно, знаете, ActionScript 3 не поддерживает перегрузку методов. Что касается VB.NET, вы можете объявлять и устанавливать переменные без явного присвоения типа, но когда вы пытаетесь передать эти переменные в качестве аргументов перегруженным методам, он все равно не хочет читать значение времени выполнения, чтобы определить, какой метод вызывать; вместо этого он хочет найти метод с аргументами типа
Object
или без типа или что-то подобное. Таким образом, приведенный выше примерint
противstring
не будет работать и на этом языке. С ++ имеет аналогичные проблемы, например, когда вы используете что-то вроде указателя void или какой-то другой механизм, подобный этому, он все равно требует, чтобы вы вручную устраняли неоднозначность типа во время компиляции.Так как первый заголовок говорит ...
Для современных языков это просто синтаксический сахар; в совершенно не зависящем от языка виде, это нечто большее. Делая перегрузку методов более полезной и актуальной, как в приведенном выше примере, на самом деле может быть хорошей функцией для добавления к существующему языку (как это было неявно запрошено для AS3), или она также может служить одним из множества фундаментальных элементов создание нового процедурного / объектно-ориентированного языка.
источник
this[chooseFunctionNameAtRandom]();
ЕслиchooseFunctionNameAtRandom()
возвращается либо"punch"
,"kick"
или"dodge"
, то вы можете константы выглядят реализовать очень простой случайный элемент, например, ИИ противника во флэш-игре.Это действительно зависит от вашего определения «синтаксического сахара». Я попытаюсь обратиться к некоторым определениям, которые приходят мне в голову:
Функция является синтаксическим сахаром, когда программа, которая ее использует, всегда может быть переведена в другую, которая не использует эту функцию.
Здесь мы предполагаем, что существует примитивный набор функций, которые нельзя перевести: другими словами, нет циклов типа «вы можете заменить функцию X с помощью функции Y» и «вы можете заменить функцию Y с функцией X». Если одно из двух истинно, то любая другая функция может быть выражена в терминах функций, которые не являются первыми, или это примитивная функция.
То же, что и в определении 1, но с дополнительным требованием, чтобы переведенная программа была такой же типобезопасной, как и первая, то есть, обескураживая, вы не теряете никакой информации.
Определение OP: функция является синтаксическим сахаром, если ее перевод не меняет структуру программы, а требует только «локальных изменений».
Давайте возьмем Haskell в качестве примера для перегрузки. Haskell обеспечивает пользовательскую перегрузку через классы типов. Например,
+
и*
операции определены вNum
классе типа и любой тип , который имеет (полный) экземпляр такого класса может быть использован с+
. Например:Одна известная вещь о классах типов в Haskell - это то, что вы можете избавиться от них . Т.е. вы можете перевести любую программу, которая использует классы типов, в эквивалентную программу, которая их не использует.
Перевод довольно прост:
Дано определение класса:
Вы можете перевести его в алгебраический тип данных:
Вот
X_P_i
иX_op_i
есть селекторы . Т.е. данное значение типа,X a
применяемоеX_P_1
к значению, вернет значение, хранящееся в этом поле, поэтому они являются функциями с типомX a -> P_i a
(илиX a -> t_i
).Для очень грубой анологии вы можете думать о значениях для типа
X a
какstruct
s, а затем ifx
имеет типX a
выражений:можно рассматривать как:
(Легко использовать только позиционные поля вместо именованных полей, но именованные поля легче обрабатывать в примерах и избегать некоторого стандартного кода).
Учитывая объявление экземпляра:
Вы можете перевести его в функцию, которая при наличии словарей для
C_1 a_1, ..., C_n a_n
классов возвращает значение словаря (то есть значение типаX a
) для типаT a_1 ... a_n
.Другими словами, приведенный выше экземпляр может быть переведен в функцию, подобную:
(Обратите внимание, что
n
может быть0
).И на самом деле мы можем определить это как:
где
op_1 = ...
вop_m = ...
приведены определения , найденные вinstance
декларации иget_P_i_T
являются функции , определенныеP_i
экземпляромT
типа (они должны существовать , потому чтоP_i
ей являются суперклассамиX
).Учитывая вызов перегруженной функции:
Мы можем явно передать словари относительно ограничений класса и получить эквивалентный вызов:
Обратите внимание, что ограничения класса просто стали новым аргументом. В
+
переведенной программе есть селектор, как описано выше. Другими словами, переведеннаяadd
функция, учитывая словарь для типа ее аргумента, сначала «распакует» фактическую функцию для вычисления результата,(+) dictNum
а затем применяет эту функцию к аргументам.Это просто очень быстрый набросок обо всем этом. Если вы заинтересованы, вы должны прочитать статьи Саймона Пейтона Джонс и соавт.
Я считаю, что подобный подход может быть использован для перегрузки и в других языках.
Однако это показывает, что если ваше определение синтаксического сахара (1), то перегрузка является синтаксическим сахаром . Потому что вы можете избавиться от этого.
Однако переведенная программа теряет некоторую информацию об исходной программе. Например, это не означает, что экземпляры для родительских классов существуют. (Даже если операции по извлечению родительских словарей по-прежнему должны быть этого типа, вы можете передавать
undefined
или другие полиморфные значения, чтобы иметь возможность создать значениеX y
без создания значений дляP_i y
, чтобы перевод не потерял все тип безопасности). Следовательно, это не синтактический сахар согласно (2)Что касается (3). Я не знаю, должен ли ответ быть да или нет.
Я бы сказал нет, потому что, например, объявление экземпляра становится определением функции. Перегруженные функции получают новый параметр (что означает, что он изменяет как определение, так и все вызовы).
Я бы сказал да, потому что две программы по-прежнему отображаются один на один, поэтому «структура» на самом деле не сильно изменилась.
Тем не менее, я бы сказал, что прагматические преимущества, вызванные перегрузкой, настолько велики, что использование «уничижительного» термина, такого как «синтаксический сахар», не кажется правильным.
Вы можете перевести весь синтаксис Haskell на очень простой язык Core (который фактически выполняется при компиляции), поэтому большую часть синтаксиса Haskell можно рассматривать как «синтаксический сахар» для чего-то, что является просто лямбда-исчислением плюс немного новыми конструкциями. Однако мы можем согласиться с тем, что программы на Haskell намного проще в обращении и очень лаконичны, тогда как переведенные программы сложнее читать или думать.
источник
Если диспетчеризация разрешается во время компиляции, в зависимости только от статического типа выражения аргумента, то вы, конечно, можете утверждать, что это «синтаксический сахар», заменяющий два разных метода с разными именами, при условии, что программист «знает» статический тип и может просто использовать правильное имя метода вместо перегруженного имени. Это также форма статического полиморфизма, но в этой ограниченной форме он обычно не очень силен.
Конечно, было бы неудобно менять имена методов, которые вы вызываете, всякий раз, когда вы меняете тип переменной, но, например, в языке C это считается управляемым неудобством, поэтому в C нет перегрузки функций (хотя теперь он имеет общие макросы).
В шаблонах C ++ и на любом языке, который выполняет нетривиальную дедукцию статического типа, вы не можете утверждать, что это «синтетический сахар», если только вы не утверждаете, что дедукция статического типа является «синтаксическим сахаром». Было бы неприятно не иметь шаблонов, а в контексте C ++ это было бы «неуправляемым неудобством», так как они настолько идиоматичны по отношению к языку и его стандартным библиотекам. Так что в C ++ это больше, чем просто хороший помощник, это важно для стиля языка, и поэтому я думаю, что вы должны называть это больше, чем «синтаксический сахар».
В Java вы можете рассмотреть это не просто как удобство, учитывая, например, сколько существует перегрузок
PrintStream.print
иPrintStream.println
. Но тогда существует столько жеDataInputStream.readX
методов, поскольку Java не перегружает возвращаемый тип, поэтому в некотором смысле это просто для удобства. Это все для примитивных типов.Я не помню, что происходит в Java, если у меня есть классы
A
иB
расширенияO
, я перегружаю методыfoo(O)
,foo(A)
иfoo(B)
, затем, в общем,<T extends O>
я вызываюfoo(t)
гдеt
экземплярT
. В том случае , когдаT
этоA
я получаю депешу на основе перегрузки или это , как если бы я назвалfoo(O)
?Если первое, то перегрузки метода Java лучше, чем сахара, так же, как перегрузки C ++. Используя ваше определение, я предполагаю, что в Java я мог бы локально написать серию проверок типов (которые были бы хрупкими, потому что новые перегрузки
foo
потребовали бы дополнительных проверок). Помимо принятия этой хрупкости, я не могу вносить локальные изменения на сайте вызовов, чтобы сделать это правильно, вместо этого мне пришлось бы отказаться от написания общего кода. Я бы сказал, что предотвращение вздутого кода может быть синтаксическим сахаром, но предотвращение хрупкого кода - это нечто большее. По этой причине статический полиморфизм в целом - это больше, чем просто синтаксический сахар. Ситуация на конкретном языке может отличаться, в зависимости от того, насколько далеко язык позволяет вам пройти, «не зная» статического типа.источник
T:Animal
это имеет типSiameseCat
и существующие перегрузки являютсяCat Foo(Animal)
,SiameseCat Foo(Cat)
иAnimal Foo(SiameseCat)
, что перегрузка должны быть выбраны , еслиT
этоSiameseCat
?long foo=Math.round(bar*1.0001)*5
меняется наlong foo=Math.round(bar)*5
. Как это повлияет на семантику, еслиbar
равно, например, 123456789L?long
вdouble
.double
?Похоже, «синтаксический сахар» звучит уничижительно, бесполезно или бесполезно. Вот почему этот вопрос вызывает много отрицательных ответов.
Но вы правы, перегрузка методов не добавляет к языку никакой функции, за исключением возможности использовать одно и то же имя для разных методов. Вы можете сделать тип параметра явным, программа все равно будет работать так же.
То же самое относится и к именам пакетов. Строка - это просто синтаксический сахар для java.lang.String.
На самом деле такой метод, как
в классе MyClass должно называться что-то вроде «my_package_MyClass_fun_int_java_lang_String». Это идентифицирует метод однозначно. (JVM делает что-то подобное внутри). Но ты не хочешь писать это. Вот почему компилятор позволит вам написать fun (1, «one») и определить, какой это метод.
Однако есть одна вещь, которую вы можете сделать с перегрузкой: если вы перегрузите метод с одинаковым количеством аргументов, компилятор автоматически определит, какая версия лучше всего подходит для аргумента, заданного соответствующими аргументами, не только с одинаковыми типами, но и где данный аргумент является подклассом объявленного аргумента.
Если у вас есть две перегруженные процедуры
вам не нужно знать, что существует конкретная версия процедуры для дат. addParameter ("hello", "world) вызовет первую версию, addParameter (" now ", new Date ()) вызовет вторую.
Конечно, вы должны избегать перегрузки метода другим методом, который делает совершенно другую вещь.
источник
Интересно, что ответ на этот вопрос будет зависеть от языка.
В частности, существует взаимодействие между перегрузкой и универсальным программированием (*), и в зависимости от того, как реализовано универсальное программирование, оно может быть просто синтаксическим сахаром (Rust) или абсолютно необходимым (C ++).
То есть, когда общее программирование реализовано с явными интерфейсами (в Rust или Haskell это были бы классы типов), тогда перегрузка является просто синтаксическим сахаром; или на самом деле может даже не быть частью языка.
С другой стороны, когда общее программирование реализовано с помощью утиной типизации (будь то динамическое или статическое), тогда имя метода является существенным контрактом, и поэтому перегрузка обязательна для работы системы.
(*) Используется в смысле написания метода один раз, чтобы работать с различными типами единообразно.
источник
В некоторых языках это, без сомнения, просто синтаксический сахар. Однако то, что это сахар, зависит от вашей точки зрения. Я оставлю это обсуждение на потом в этом ответе.
Сейчас я просто хотел бы отметить, что в некоторых языках это, конечно, не синтаксический сахар. По крайней мере, без необходимости использовать совершенно другую логику / алгоритм для реализации одной и той же вещи. Это все равно что утверждать, что рекурсия - это синтаксический сахар (так как вы можете написать весь рекурсивный алгоритм с циклом и стеком).
Один пример очень трудного для замены использования взят из языка, который по иронии судьбы не называет эту функцию «перегрузкой функции». Вместо этого это называется «сопоставление с образцом» (которое можно рассматривать как расширенный набор перегрузок, поскольку мы можем перегружать не только типы, но и значения).
Вот классическая наивная реализация функции Фибоначчи в Haskell:
Возможно, три функции могут быть заменены на if / else, как это обычно делается на любом другом языке. Но это в основном делает совершенно простое определение:
гораздо сложнее и прямо не выражает математическое понятие последовательности Фибоначчи.
Поэтому иногда это может быть синтаксическим сахаром, если единственное использование - позволить вам вызывать функцию с разными аргументами. Но иногда это гораздо более фундаментально, чем это.
Теперь для обсуждения того, для чего перегрузка оператора может быть сахаром. Вы определили один вариант использования - его можно использовать для реализации похожих функций, которые принимают разные аргументы. Так:
альтернативно может быть реализован как:
или даже:
Но перегрузка операторов также может быть сахаром для реализации необязательных аргументов (некоторые языки имеют перегрузку операторов, но не необязательные аргументы):
может быть использован для реализации:
На таком языке (Google "Ferite language") удаление перегрузки операторов резко удаляет одну особенность - необязательные аргументы. Допускается, что в языках с обеими функциями (c ++) удаление одного или другого не будет иметь никакого эффекта, поскольку любой из них может быть использован для реализации необязательных аргументов.
источник
data PaymentInfo = CashOnDelivery | Adress String | UserInvoice CustomerInfo
вы, вы можете сопоставить шаблон с конструкторами типов.getPayment :: PaymentInfo -> a
getPayment CashOnDelivery = error "Should have been paid already"
getPayment (Adress addr) = -- code to notify administration to send a bill
getPayment (UserInvoice cust) = --whatever. I took the data type from a Haskell tutorial and have no idea what an invoice is
. Я надеюсь, что этот комментарий несколько понятен.Я думаю, что это простой синтаксический сахар в большинстве языков (по крайней мере, все, что я знаю ...), так как все они требуют однозначного вызова функции во время компиляции. И компилятор просто заменяет вызов функции явным указателем на правильную сигнатуру реализации.
Пример в Java:
Таким образом, в конце он может быть полностью заменен простым макросом-компилятором с поиском и заменой, заменяя перегруженные функции mangle на mangle_String и mangle_int - поскольку список аргументов является частью возможного идентификатора функции, это практически то, что происходит -> и поэтому это только синтаксический сахар.
Теперь, если есть язык, где функция действительно определяется во время выполнения, как с переопределенными методами в объектах, это было бы иначе. Но я не думаю, что существует такой язык, так как method.overloading подвержен неоднозначности, которую компилятор не может разрешить и которая должна быть обработана программистом с явным приведением. Это не может быть сделано во время выполнения.
источник
В Java информация о типе компилируется, и какая из перегрузок вызывается, решает во время компиляции.
Ниже приведен фрагмент из
sun.misc.Unsafe
(утилита для Atomics), который просматривается в редакторе файлов классов Eclipse.Как вы можете видеть, информация о типе вызываемого метода (строка 4) включена в вызов.
Это означает, что вы можете создать Java-компилятор, который принимает информацию о типе. Например, используя такую запись, источник вышеупомянутого будет:
и приведение к длинному будет необязательным.
В других статически типизированных языках компиляции вы увидите похожую настройку, в которой компилятор решит, какая перегрузка будет вызываться в зависимости от типов, и включит ее в привязку / вызов.
Исключение составляют динамические библиотеки C, в которые не включена информация о типах, и попытка создать перегруженную функцию приведет к тому, что компоновщик будет жаловаться.
источник