Почему я должен перегружать методы?
Я нашел два примера в своей книге методов перегрузки, но это не объясняет точно, почему это полезно:
package keepo;
public class Main{
public static void main(String [] args)
{
int newScore = calculateScore("Tim", 500);
System.out.println("New Score is" + newScore);
calculateScore(75);
}
public static int calculateScore(String playerName, int score){
System.out.println("Player" + playerName +"Has score" + score);
return score * 1000;
}
public static int calculateScore(int score){
System.out.println("Unnamed player scored" + score + "points");
return score * 1000;
}
}
Это довольно просто, но, честно говоря, кажется довольно бесполезным перегружать метод здесь, и кажется, что он просто делает это ради этого.
следующий пример в книге делает перегрузку метода, которая кажется немного более полезной, потому что эта программа вычисляет ноги до сантиметров, и есть один метод, где вы можете поместить ноги и дюймы, и один метод, где вы можете положить дюймы. Тем не менее, по-прежнему кажется так же легко сделать два отдельных метода для этого.
это, как говорится,есть ли реальные преимущества в этом? (Я читаю этой, но я действительно не удовлетворен. Кажется, так же легко создавать новые методы.)
6 ответов
Я думаю, если вы говорите о реальных преимуществах перегрузки функций / методов, чего-то, без чего вы не сможете обойти, то, как вы указали в своем вопросе, вы не найдете.
но как это поможет? Рассмотрим этот пример.
предположим, что я делаю приложение, которое находит человека по его имени и я объявить и определить метод
public Person[] findPerson(String name)
теперь мы получаем требование, где мы должны найти человека по его Дата рождения, поэтому ввести новый метод
public Person[] findPerson_byDOB(Date date)
предположим, что это продолжается, и у нас есть много методов в моем приложении.
public Person[] findPerson(String name)
public Person[] findPerson_byDOB(Date date)
public Person[] findPerson_byAddress(Address address)
public Person[] findPerson_bySSN(SSN ssn)
public Person[] findPerson_byDepartment(Department department)
public Person[] findPerson_byMobile(Mobile mobile)
это только одна часть; это может продолжаться, когда нас попросят ввести несколько параметров, таких как
public Person[] findPerson_byMobileAndAddress(Mobile mobile, Address address)
public Person[] findPerson_byAddressAndDepartment(Address address, Department department)
public Person[] findPerson_byDOBAndDepartment(DOB dob, Department, department)
public Person[] findPerson_byAddressAndDOB(Address address, DOB dob)
и многое другое...
хотя это может показаться немного преувеличенным, поверьте мне, при создании фактического приложения отраслевого уровня мы можем столкнуться с ситуацией, когда получим сотни и сотни таких методов, и в конечном счете нам понадобится каталог всех этих методов того, что они на самом деле делают.
это на самом деле кошмар, когда нам придется найти название всех этих методов, когда мы должны использовать его.
однако, когда все параметры различны, мы можем дать одно и то же имя функции, и это действительно становится очень легко запомнить.
public Person[] findPerson(String name)
public Person[] findPerson(Date date)
public Person[] findPerson(Address address)
public Person[] findPerson(SSN ssn)
public Person[] findPerson(Department department)
public Person[] findPerson(Mobile mobile)
public Person[] findPerson(Mobile mobile, Address address)
public Person[] findPerson(Address address, Department department)
public Person[] findPerson(DOB dob, Department, department)
public Person[] findPerson(Address address, DOB dob)
теперь, как указал Дэвид в ответ, мы все знать, как получить String
значение целого числа; вероятно, мы его где-то читали.
static String.valueOf(new Integer(1));
но знаете ли вы, сколько еще методов перегружены с тем же именем?
static String.valueOf(boolean b)
static String.valueOf(char c)
static String.valueOf(char[] data)
static String.valueOf(double d)
static String.valueOf(float f)
static String.valueOf(int i)
static String.valueOf(long l)
static String.valueOf(Object obj)
преимущества заключаются в том, что вам не нужно запоминать их все. Вам даже не нужно догадываться, потому что это одно и то же имя.
редактировать как за советы по Namnodorel
считайте это перегруженным метод PrintStream
класса.
void println()
void println(boolean x)
void println(char x)
void println(char[] x)
void println(double x)
void println(float x)
void println(int x)
void println(long x)
void println(Object x)
void println(String x)
просто подумайте о читаемости, если бы нам пришлось написать:
void println_emptyLine()
void println_boolean(boolean x)
void println_character(char x)
void println_characterArray(char[] x)
void println_double(double x)
void println_float(float x)
void println_integer(int x)
void println_long(long x)
void println_object(Object x)
void println_string(String x)
перегрузка полезна, когда вы делаете методы, которые делают то же самое со значениями другого типа.
Math
класс предоставляет идеальный пример - он имеет группы перегрузки функций по типу-четыре abs
, четыре min
, четыре max
и так:
int max(int a, int b) {...}
float max(float a, float b) {...}
long max(long a, long b) {...}
double max(double a, double b) {...}
альтернатива без перегрузки заставит вас "кодировать" тип в имя вашего метода, например Math.intMax(a, b)
что было бы пагубно для удобочитаемости кода пользователя.
быть простым и кратким:
Перегрузка-это просто возможность, предоставляемая Java (но большинство современных и гибких языков использовать его) (и другие языки, такие как C++ или C#), чтобы позволить разработчикам создавать для одного и того же имени метода/функции несколько из них.
почему ?
Потому что именование метода важно, и именование метода должно передавать его поведение.
Итак, если два метода имеют одинаковое поведение (например, преобразование в строку)
но чем в пока input и чем другой использует int в качестве ввода, почему имеет другое имя метода ?
String myString = String.valueOf(new Integer(1));
String myOtherString = String.valueOf(new Long(2));
намерение и цель одинаковы, меняются только входные параметры.
когда перегрузка имеет смысл, вы должны использовать ее вместо создания некоторых вариантов неуклюжих имен.
перегрузка метода полезна в следующем сценарии:
считайте, у вас есть класс, который отслеживает список имен. У вас есть стиль кода выше, где каждый метод имеет свой собственный подход к выполнению операций над этим списком имен.
внезапно внутреннее представление списка изменяется (возможно, из array
до ArrayList
, это не имеет значения). Вы хотите быть ответственным за рефакторинг каждый. один. метод?
перегрузка метода полезна, потому что тогда вы можете маршрутизировать все операции через один общий метод. Это означает, что всякий раз, когда внутреннее представление изменяется, вам нужно только изменить этот общий метод, и все ваши другие специализированные методы все еще работают одинаково.
кроме того, рассмотрим приведенный пример. Что произойдет, если вы хотите изменить способ печати сообщения программой? Вам придется изменить оба метода чтобы напечатать сообщение того же типа, кошмар обслуживания. Конечно, сейчас это кажется небольшим, но подумайте о том, когда ваш проект растет, и вы начинаете иметь гораздо больше методов, полагающихся на этот (эффективно фиксированный) формат сообщений.
Я объект, и у меня есть возможность, возможность фиксирована, но может принимать различные параметры.
если возможность может принять 1000 виды параметров, вы хотите, чтобы ломать голову, чтобы думать о 1000 имен возможностей?
возьмите другие сообщения как хорошую практику перегрузки и возьмите то, что jnienv делает как плохую практику, потому что C не поддерживает перегрузку.
CallStaticObjectMethod,
CallStaticObjectMethodV,
CallStaticObjectMethodA,
CallStaticBooleanMethod,
CallStaticBooleanMethodV,
CallStaticBooleanMethodA,
CallStaticByteMethod,
CallStaticByteMethodV,
CallStaticByteMethodA,
CallStaticCharMethod,
CallStaticCharMethodV,
CallStaticCharMethodA,
CallStaticShortMethod,
CallStaticShortMethodV,
CallStaticShortMethodA,
CallStaticIntMethod,
CallStaticIntMethodV,
CallStaticIntMethodA,
CallStaticLongMethod,
CallStaticLongMethodV,
CallStaticLongMethodA,
CallStaticFloatMethod,
CallStaticFloatMethodV,
CallStaticFloatMethodA,
CallStaticDoubleMethod,
CallStaticDoubleMethodV,
CallStaticDoubleMethodA,
CallStaticVoidMethod,
CallStaticVoidMethodV,
CallStaticVoidMethodA,
Reger к JNI, у для более подробной структуры определение
другой причиной перегрузки является предоставление одного или нескольких аргументов по умолчанию.
рассмотрим следующее:
class Something {
// Imagine that this is a real class, that does real work.
public void doSomething(boolean b, char c, double d, int i) {
// Imagine that this is one of the main components of class Something.
System.out.println("Hi. You passed: " + b + ", " + c + ", " + d + ", and " + i + ".");
}
public void doSomething(boolean b, char c, double d) {
doSomething(b, c, d, 42);
}
public void doSomething(boolean b, char c) {
doSomething(b, c, 1.3579);
}
public void doSomething(boolean b) {
doSomething(b, 'q');
}
public void doSomething() {
doSomething(true);
}
}
в этом примере каждая перегрузка предоставляет значение по умолчанию для одного из параметров, связывая их вместе, пока вы не получите полный вызов версии doSomething()
это действительно делает работу.
Something s = new Something();
Something t = new Something();
Something u = new Something();
// ...
s.doSomething(true, 'c', 2.9);
t.doSomething(false, 'z');
u.doSomething();
посмотреть здесь для примера.