Каково использование/преимущество перегрузки функции?
Перегрузка - это форма полиморфизма. Это позволяет программисту писать функции, которые концептуально делают одно и то же с разными типами данных без изменения имени. (Это также позволяет программисту писать функции для выполнения концептуально разных вещей в зависимости от параметров, но это очень плохая идея.)
Это обеспечивает согласованность в обозначениях, что хорошо как для чтения, так и для написания кода. Ввод-вывод - очень распространенное использование. В большинстве широко используемых языков есть функция или оператор, которые будут выводить все, что угодно, например printf ()
и kin в C, operator << ()
в C ++, PRINT
в старых ОСНОВАХ, которые я использовал, что угодно. Языки, требующие таких функций, как printint ()
, printstring ()
, printfloat ()
и т.п., никогда не прижились.
Он очень хорошо работает с шаблонами C ++ и любыми другими конструкциями, в которых вы не обязательно знаете тип переменной на момент написания кода.
Ваша функция может захотеть работать с некоторыми необязательными деталями. Например, следующий пример хочет добавить члена в объект Members с любыми деталями, известными пользователю. Здесь возраст является минимальной деталью для создания члена, возраст и memberOf являются необязательными. [Примечание: определение функций не приведено в фрагменте кода.]
public class Members
{
public System.Collections.Generic.List TeamMembers;
public AddMember(Member m) {}
public AddMember(string name) {}
public AddMember(string name, int age) {}
public AddMember(string name, int age, string[] memberOf) {}
public class Member
{
public string Name { get; set; }
public int Age { get; set; }
public string[] MemberOf { get; set; }
}
}
Вы можете захотеть, чтобы ваш метод подходил для нескольких типов объектов. Например. Метод Console.WriteLine() способен вывести на консоль пустую строку, bool, int, string, char[], float и т.д. Это стало возможным благодаря перегрузке функций.
Функция / метод иногда может принимать различные типы параметров для выполнения своей работы. Это время для перегрузки функций. В противном случае вам пришлось бы иметь разные функции для одной и той же функции , что сбивает с толку и является плохой практикой.
Это обеспечивает множественное поведение одного и того же объекта по отношению к атрибутам объекта.
Например, метод под названием addUs(a,b)
добавляет a
и b
.
Таким образом, определение будет следующим:
int addUs(int a, int b){
return a+b;
}
Но теперь, если вы хотите, чтобы ваши аргументы были объектами класса, скажем:
class Demo{
int height;
int width;
}
Вы хотите, чтобы та же функция addUs()
вернула новый объект, который будет иметь атрибуты height и width, имеющие значения как сумма высоты и ширины двух переданных аргументов.
Итак, теперь определение будет выглядеть так:
Demo addUs(Demo a Demo b){
Demo this;
this.height = a.height + b.height;
this.width = a.width + b.width;
return this;
}
Иногда у вас есть несколько способов выполнить одно и то же в зависимости от контекста и доступных входных данных. Для статических языков со строгим типом определения функций могут быть довольно жесткими и должны быть явно определены заранее.
Конструкторы, как правило, являются лучшим классическим примером этого. Если вы создаете сложный объект и у вас нет всех частей, вы все равно хотите иметь возможность передать то, что у вас есть, конструктору и позволить ему заполнить остальное. А то, что у вас есть, может сильно различаться и должно определяться по-разному в качестве параметров для конструкторов.
ИМО, основным преимуществом является единообразие в именовании методов / функции, которые логически выполняют очень похожие задачи и немного отличаются друг от друга, принимая разные параметры. Это позволяет повторно использовать одно и то же имя метода в нескольких реализациях.
например. Перегрузки: (Хорошо)
function Person[] FindPersons(string nameOfPerson) { ... }
function Person[] FindPersons(date dateOfBirth) { ... }
function Person[] FindPersons(int age, string dogsName) { ... }
Предпочтительнее функций с «уникальными именами»: (Хуже)
function Person[] FindPersonsByName(string nameOfPerson) { ... }
function Person[] FindPersonsByDOB(date dateOfBirth) { ... }
function Person[] FindPersonsByAgeAndDogsName(int age, string dogsName) { ... }
Таким образом, кодер, пишущий клиента, который вызывает / использует эти функции, может работать на более высоком уровне концептуального мышления («Мне нужно найти человека ") и не нужно запоминать / находить вымышленное имя функции.
При статической типизации компилятору будет предоставлена возможность сопоставить применимую перегрузку на основе параметров использования. Для динамической типизации такое же совпадение произойдет во время выполнения, что может привести к сбою, если подходящее совпадение не будет найдено.
Очень актуальный вопрос.
Вы получаете единообразие в именовании, но за счет двусмысленности в отношении точной реализации .
Настоящая проблема - человеческая память о имена методов, верно? мы находим это легче запомнить имена, которые обычно используется.
и экономия печати, позволяющая более короткие имена методов? меньше разных имена означает (математически), что само название несет меньше информации.
Эти две проблемы не должны вызывать беспокойства, если IDE быстро находят / угадывают / вставляют имена методов на основе первых нескольких символов и типов параметров / возвращаемых значений.
Но я думаю, что точность кодирования имеет свои издержки, а также пользу.
Возможно, вы захотите проделать похожие вещи в коде с другими параметрами. Если бы вам пришлось дать каждой функции другое имя, читабельность кода была бы очень плохой.