我为什么要重载方法?

时间:2016-07-23 01:40:31

标签: java function oop overloading

我在我的重载方法书中找到了两个例子,但它并没有清楚地解释为什么它有用:

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

这非常简单,但说实话,这里的方法重载似乎毫无用处,而且它似乎只是为了做到这一点。

本书中的下一个例子是方法重载,它似乎更有用,因为该程序计算英尺到厘米,有一种方法可以放入英尺和英寸,还有一种方法可以放英寸。但是,为此制作两个单独的方法似乎同样容易。

话虽如此,这样做有什么好处吗? (我读过this,但我并不满意。制作新方法似乎同样容易。)

6 个答案:

答案 0 :(得分:63)

我认为如果你谈论功能/方法重载的真正好处,没有它你就无法解决问题,那么正如你在问题中指出的那样,你将找不到任何东西。

但它有什么用?让我们考虑这个例子。

让我们假设我正在创建一个通过他的名字找到一个人的应用程序,然后我声明并定义一个方法

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)

现在大卫在his answer中指出,我们都知道如何获得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 class的这个重载方法。

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)

答案 1 :(得分:22)

当您使用不同类型的值创建相同的方法时,重载非常有用。

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)这会对用户代码的可读性产生不利影响。

答案 2 :(得分:2)

简单明了: Java (但大多数现代和灵活的语言使用它)(和其他语言,如C ++或C#)提供重载只是一种可能性,允许开发人员创建相同的方法/函数名称,几个它的。

为什么?
因为方法命名很重要,方法命名应该传达它的行为。 所以,如果两个方法具有相同的行为(例如转换为字符串) 但是,除了一个使用long作为输入,而另一个使用int作为输入,为什么有一个不同的方法名称?

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


意图和目标是一样的,只是输入参数改变。

当重载有意义时​​,您应该使用它而不是创建一些变体笨拙的名称。

答案 3 :(得分:1)

方法重载在以下场景中很有用:

假设您有一个跟踪名称列表的类。您拥有上面的代码样式,其中每个方法都有自己对此名称列表执行操作的承诺。

突然,列表的内部表示发生了变化(可能从myDataBase.execSQL("UPDATE some_table SET some_column='" + value + "' WHERE some_column LIKE '" + some_value + "'"); 变为array,这并不重要。你想成为负责重构每个的人吗? 。方法

方法重载很有用,因为您可以通过单个通用方法路由所有操作。这意味着每当内部表示发生更改时,您只需更改该泛型方法,并且所有其他专用方法仍然可以正常工作。

另外,请考虑您提供的示例。如果要更改程序打印消息的方式会发生什么?您将不得不修改两种方法来打印相同类型的消息,这是一个维护噩梦。当然,它现在似乎很小,但考虑一下你的项目何时增长,并且你开始有更多的方法依赖于这种(有效修复的)消息格式。

答案 4 :(得分:1)

我是一个对象,我有能力,功能是固定的,但可以接受各种参数。

如果该功能可以接受 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 to JNI以获取更详细的结构定义

答案 5 :(得分:1)

重载的另一个原因是提供一个或多个默认参数。

请考虑以下事项:

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

有关示例,请参阅here