Подтвердить что ты не робот

Почему я должен перегружать методы?

В моей книге методов перегрузки я нашел два примера, но он не объясняет четко, почему это полезно:

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;
    }
}

Это довольно просто, но, честно говоря, здесь бесполезно перегружать метод, и, похоже, он просто делает это ради этого.

Следующий пример в книге перегружает метод, который кажется немного более полезным, потому что эта программа вычисляет ножки до сантиметров, и есть один метод, где вы можете положить ноги и дюймы, а также один метод, где вы можете установить дюймы. Тем не менее, по-прежнему представляется так же легко сделать два разных метода для этого.

Как говорится, есть ли реальные выгоды для этого? (Я читал этот, но я не очень доволен. Кажется, так же легко создавать новые методы.)

4b9b3361

Ответ 1

Я думаю, если вы расскажете о реальных преимуществах перегрузки функций/методов, то без чего вы не сможете обойтись, то, как вы указали в своем вопросе, вы не найдете их.

Но как это полезно? Рассмотрим этот пример.

Предположим, что я делаю приложение, которое находит человека по его имени, и я объявляю и определяю метод

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 integer; вероятно, мы его где-то читали.

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)

Преимущества заключаются в том, что вам не нужно запоминать их все. Вам даже не нужно гадать, потому что это одно и то же имя.


РЕДАКТИРОВАТЬ согласно рекомендациям Намнодорела

Рассмотрим этот перегруженный метод класса 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)

Ответ 2

Перегрузка полезна, когда вы создаете методы, которые делают то же самое со значениями другого типа.

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), что ухудшает читаемость кода пользователя.

Ответ 3

Чтобы быть простым и кратким: Перегрузка - это просто возможность, предоставляемая Java (но использует большинство современных и гибких языков) (и другие языки, такие как С++ или С#), чтобы разработчики могли создавать одно и то же имя метода/функции, несколько из этого.

Почему?
Поскольку имя метода важно, а имя метода должно передавать его поведение. Итак, если два метода имеют одно и то же поведение (например, преобразование в строку) но чем один использует длинный ввод, а другой использует int как вход, почему с другим именем метода?

    String myString = String.valueOf(new Integer(1));
    String myOtherString = String.valueOf(new Long(2));


Цель и цель одинаковы, только изменения входных параметров.

Когда перегрузка имеет смысл, вы должны использовать ее вместо того, чтобы создавать некоторые возможные неуклюжие имена.

Ответ 4

Перегрузка метода полезна в следующем сценарии:

У вас есть класс, который отслеживает список имен. У вас есть стиль кода выше, где каждый метод имеет свои собственные операции по выполнению операций над этим списком имен.

Вдруг внутреннее представление списка изменяется (возможно, от array до ArrayList, это не имеет большого значения). Вы хотите быть ответственным за рефакторинг каждого. Один. метод?

Перегрузка метода полезна, потому что тогда вы можете маршрутизировать все операции с помощью одного, общего метода. Это означает, что всякий раз, когда изменяется внутреннее представление, вам нужно только изменить этот общий метод, и все ваши другие специализированные методы все равно будут работать одинаково.


Также рассмотрите предоставленный вами пример. Что произойдет, если вы хотите изменить, как программа печатает сообщение? Вам придется изменить оба метода, чтобы напечатать однотипное сообщение, кошмар обслуживания. Конечно, сейчас это кажется маленьким, но подумайте о том, когда ваш проект будет расти, и вы начнете использовать еще много методов, основанных на этом (эффективно фиксированном) формате сообщений.

Ответ 5

Я объект, и у меня есть возможность, возможность исправлена, но может принимать различные параметры.

Если возможности могут принимать типы 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 для более подробного определения структуры

Ответ 6

Еще одна причина перегрузки - предоставить один или несколько аргументов по умолчанию.

Рассмотрим следующее:

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();

См. здесь для примера.