public String get(String arg0, String arg1, String arg2) {
// do stuff
}
public String get(String arg0, String arg1) {
return method(arg0, arg1, null);
}
public String method(String arg0) {
return method(arg0, null, null);
}
可以通过构建器进行改进:
class Request {
final String arg0;
final String arg1;
final String arg2;
private Request(Builder b) {
this.arg0 = b.arg0;
this.arg1 = b.arg1;
this.arg2 = b.arg2;
}
// getter methods
public static class Builder {
String arg0, arg1, arg2;
public Builder arg0(String arg) {
this.arg0 = arg;
return this;
}
public Builder arg1(String arg) {
this.arg1 = arg;
return this;
}
public Builder arg2(String arg) {
this.arg2 = arg;
return this;
}
public Request build() {
return new Request(this);
}
}
}
class Client {
public String get(Request request) { }
}
new Client().get(Request.Builder().arg0("arg0").arg1("arg1").arg2("arg2").build());
我经常做的另一个重载是方法可以接受不同数据类型的参数:
public String lookup(String variant) {
return lookup(Integer.parseInt(variant));
}
public String lookup(int ordinal) {
// logic
}
Method overloading is useless if your intent is solely parameter sequence, because IMHO, you're just encouraging boilerplate code (repeating identical code), and if the parameters are all of the same data type, you'll receive a compilation error because the method signatures are ambiguous.
I do a lot of method overloading in APIs for convenience purposes when a parameter can exist as multiple data types:
public class Client {
public Status get(String request) {
return get(new Request(request));
}
public Status get(Request request) {
// do stuff
}
}
If you have a lot of parameters, and many of them are optional, I would suggest looking into the Builder pattern. The intent of the builder pattern is to create an immutable object constructed of optional parameters. For instance:
public String get(String arg0, String arg1, String arg2) {
// do stuff
}
public String get(String arg0, String arg1) {
return method(arg0, arg1, null);
}
public String method(String arg0) {
return method(arg0, null, null);
}
can probably be improved with a builder:
class Request {
final String arg0;
final String arg1;
final String arg2;
private Request(Builder b) {
this.arg0 = b.arg0;
this.arg1 = b.arg1;
this.arg2 = b.arg2;
}
// getter methods
public static class Builder {
String arg0, arg1, arg2;
public Builder arg0(String arg) {
this.arg0 = arg;
return this;
}
public Builder arg1(String arg) {
this.arg1 = arg;
return this;
}
public Builder arg2(String arg) {
this.arg2 = arg;
return this;
}
public Request build() {
return new Request(this);
}
}
}
class Client {
public String get(Request request) { }
}
new Client().get(Request.Builder().arg0("arg0").arg1("arg1").arg2("arg2").build());
Another overload that I do a lot is when a method can accept parameters of varying data types:
public String lookup(String variant) {
return lookup(Integer.parseInt(variant));
}
public String lookup(int ordinal) {
// logic
}
public String buildUrl(String protocol, String host, int port){
return protocol + "://" + host + ":" + port;
}
public String buildUrl(String protocol, int port, String host){
return protocol + "://" + host + ":" + port;
}
So, I was thinking that this was useless. But there might be a case like this (took a long time to come up with it :-)) -
public int countTotalTruckWheels(boolean hasSpare, int numberOfTrucks){
if(hasSpare){
return (numberOfTrucks+1)*4;
} else{
return numberOfTrucks*4;
}
}
public int countTotalTruckWheels(int numberOfAxlesInTruck, boolean strongAxle){
if(strongAxle){
//each axle can hold 4 wheels
return numberOfAxlesInTruck*4;
} else {
return numberOfAxlesInTruck*2;
}
}
Here the datatypes of the parameters are not just re-ordered, but the entire meaning of the parameters has been changed.
I understood this based on many answers above. I am unable to choose one particular answer. Also, I wanted to add this as a comment, but it was too big to be a comment. Hence added it here.
It also said that the argument list could differ in (iii). Sequence of parameters
(iii) is simply wrong. You can't change overload by simply changing the order of the parameters. Take this example:
int add(int x, int y)
int add(int y, int x)
This is not a legal overloading. Now consider this example:
int fill(int number, char c)
int fill(char c, int number)
Remember the parameter names don't matter, so really, it looks like this to the compiler:
int pad(int, char)
int pad(char, int)
This is valid overloading, but not because you changed the order of the parameters, but rather because the types of one or more of the parameters changed. The two methods differ because the type of the 1st parameter is different between the methods (as is the type of the 2nd parameter).
What is the use of trying to overload a method just by changing the sequence of parameters?
There is no use. The text is NOT saying you "SHOULD" do method overloading by changing the sequence of parameters, the text is only saying that its possible (as long as the reordering creates a unique parameter signature). This is simply a consequence (a side-effect) of how overloading works - I feel certain in saying that it is not an use case that the language designers were trying to support. Put another way:
Just because you can do it, doesn't mean you should.
There are not many reasons to do that sort of overloading, but I can think of a couple.
Your API goes public, and all your method signatures but one for a fairly common (but uninherited) method are the same. Say they're all myFunct(String,int) and one of them happens to be myFunct(int,String) by accident. You will want to keep that function for backwards compatibility, but you'll also probably make that one class also have myFunct(String,int) to keep it consistent.
Another reason (even if it is a poor one) is that you may have people used to them in one order, perhaps from a different library, or maybe they're just dyslexic... but you might overload it to swap parameters if it's convenient to do so. Obviously, this can be tricky, because if you have (String,int,int) You probably don't want to do (int,int,String) or (int,String,int) ALSO. Best to keep it to just one.
int raise(int i, String n);
int raise(String i, int n);
正如您在数学课上很早就学到的那样,用一个值求另一个值是一种非交换运算(即 2^3 != 3^2)。
因此,在这个例子中,每个方法都会通过另一个方法来提高一些数值。第一个参数始终是要由第二个参数给出的值引发的值(顺序很重要)。但是,正如您所看到的,参数列表的每个参数都可以由 String 或 int 类型表示。然而,操作的语义保持不变。
raise("12", 2);
raise(12, "2");
当然,出于显而易见的原因,这是一个非常人为的示例,但您可以看到原则上它是合理的。
我确信如果我多给它一点,我可以想出一个更好的例子,其中参数是某种特殊类型,这种事情更有意义。
It may seem somewhat pointless and in a lot of cases I can see why some people may simply shuffle parameter sequences around simply to support overloading where really they just have poorly designed code. However, it in some circumstances it make perfect sense.
Most programmers will choose certain parameter sequences based on a notion that such parameters make more sense in a particular order or because order is in-fact fundamentally important to the outcome of some calculation. Take these overloaded methods as an example:
int raise(int i, String n);
int raise(String i, int n);
As you learned very early on in math class, raising one value by another is a non-commutative operation (i.e. 2^3 != 3^2).
So in this example, each method will raise some numeric value by another. The first parameter is always the value that is intended to be raised by the value given as second parameter (order is important). However, as you can see, each argument to the parameter list may be represented by a String or an int type. The semantics of the operation however remains the same.
raise("12", 2);
raise(12, "2");
Of course this is a very contrived example for obvious reasons, but you can see how in principle it is reasonable.
I'm sure if i gave it a bit more though I could come up with a better example where the parameters are of some special type where this sort of thing makes even more sense.
Parameter lists are determined by the number and types of the parameters. So if your parameters have different types, re-ordering the parameters gives a different overload because the compiler sees different types in different slots.
f(int a, String b)
f(String b, int a)
Both functions have two parameters but the types don't match so they are valid overloads.
As to why you might want to do this, it is often the case that the order of the parameters matters. In the codebase I maintain we have Exceptions that potentially have a cause, a message, and other parameters. So the following two calls are not the same:
Exception cause;
String msgFormat = "An error occurred while processing {0}";
String recordName = "abc123";
throw new ABCException(cause, message, recordName);
throw new ABCException(message, cause, recordName);
throw new ABCException(message, recordName);
throw new ABCException(recordName, message);
In the first case cause is the cause of the exception, message is the message to display, and record is the parameter for the message. In the second case both cause and recordName are interpreted as parameters for the message. In the third case there is no cause and in the fourth case there is no cause and furthermore the message argument is in the wrong position and won't be processed properly.
This is accomplished by having several useful overloads of the ABCException constructor (though in this case we are using varargs to support unlimited numbers of parameters).
发布评论
评论(8)
(iii)只是(ii)的一个特例。
“int, long, String”和“String, int, long”是 (ii) = 不同的数据类型,但恰好是同一组类型。
但是,混杂的重载会导致代码混乱。
(iii) is just a special case of (ii).
"int, long, String" and "String, int, long" are (ii) = different datatypes, but just happen to be the same set of types.
But yeah, promiscuous overloading leads to confusing code.
如果您的意图只是参数序列,则方法重载是无用的,因为恕我直言,您只是鼓励样板代码(重复相同的代码),并且如果参数全部具有相同的数据类型,您将收到编译错误,因为该方法签名不明确。
当参数可以作为多种数据类型存在时,为了方便起见,我在 API 中进行了很多方法重载:
如果您有很多参数,并且其中许多参数是可选的,我建议查看 构建器模式。构建器模式的目的是创建一个由可选参数构造的不可变对象。例如:
可以通过构建器进行改进:
我经常做的另一个重载是方法可以接受不同数据类型的参数:
Method overloading is useless if your intent is solely parameter sequence, because IMHO, you're just encouraging boilerplate code (repeating identical code), and if the parameters are all of the same data type, you'll receive a compilation error because the method signatures are ambiguous.
I do a lot of method overloading in APIs for convenience purposes when a parameter can exist as multiple data types:
If you have a lot of parameters, and many of them are optional, I would suggest looking into the Builder pattern. The intent of the builder pattern is to create an immutable object constructed of optional parameters. For instance:
can probably be improved with a builder:
Another overload that I do a lot is when a method can accept parameters of varying data types:
啊!有道理!我的想法是 -
所以,我认为这是没有用的。但可能存在这样的情况(花了很长时间才想出来:-)) -
这里参数的数据类型不仅仅是重新排序,而且参数的整个含义已经改变。
我根据上面的许多答案理解了这一点。我无法选择一个特定的答案。另外,我想将其添加为评论,但它太大了,无法成为评论。因此在这里添加了它。
Ah! Makes sense! I was thinking in the lines of -
So, I was thinking that this was useless. But there might be a case like this (took a long time to come up with it :-)) -
Here the datatypes of the parameters are not just re-ordered, but the entire meaning of the parameters has been changed.
I understood this based on many answers above. I am unable to choose one particular answer. Also, I wanted to add this as a comment, but it was too big to be a comment. Hence added it here.
(iii) 是完全错误的。您不能通过简单地更改参数的顺序来更改重载。举个例子:
这不是合法的重载。现在考虑这个例子:
记住参数名称并不重要,所以实际上,对于编译器来说它看起来像这样:
这是有效的重载,但不是因为你改变了参数的顺序,而是因为一个或多个参数的类型发生了变化。这两种方法有所不同,因为方法之间的第一个参数的类型不同(第二个参数的类型也是如此)。
没有用。文本不说您“应该”通过更改参数序列来进行方法重载,文本只是说它是可能的(只要重新排序创建唯一的参数签名)。这只是重载工作原理的结果(副作用)——我可以肯定地说,这不是语言设计者试图支持的用例。换句话说:
(iii) is simply wrong. You can't change overload by simply changing the order of the parameters. Take this example:
This is not a legal overloading. Now consider this example:
Remember the parameter names don't matter, so really, it looks like this to the compiler:
This is valid overloading, but not because you changed the order of the parameters, but rather because the types of one or more of the parameters changed. The two methods differ because the type of the 1st parameter is different between the methods (as is the type of the 2nd parameter).
There is no use. The text is NOT saying you "SHOULD" do method overloading by changing the sequence of parameters, the text is only saying that its possible (as long as the reordering creates a unique parameter signature). This is simply a consequence (a side-effect) of how overloading works - I feel certain in saying that it is not an use case that the language designers were trying to support. Put another way:
进行这种超载的理由并不多,但我能想到几个。
您的 API 公开,并且除了相当常见(但未继承)的方法之外的所有方法签名都是相同的。假设它们都是 myFunct(String,int) ,其中之一碰巧是 myFunct(int,String) 。您将希望保留该函数以实现向后兼容性,但您也可能使该类也具有 myFunct(String,int) 以保持一致。
另一个原因(即使它是一个糟糕的)是你可能会让人们以一种顺序习惯它们,可能来自不同的图书馆,或者可能他们只是有诵读困难......但是如果它是,你可能会重载它来交换参数这样做方便。显然,这可能很棘手,因为如果您有 (String,int,int) 您可能也不想执行 (int,int,String) 或 (int,String,int) 。最好只保留一个。
There are not many reasons to do that sort of overloading, but I can think of a couple.
Your API goes public, and all your method signatures but one for a fairly common (but uninherited) method are the same. Say they're all myFunct(String,int) and one of them happens to be myFunct(int,String) by accident. You will want to keep that function for backwards compatibility, but you'll also probably make that one class also have myFunct(String,int) to keep it consistent.
Another reason (even if it is a poor one) is that you may have people used to them in one order, perhaps from a different library, or maybe they're just dyslexic... but you might overload it to swap parameters if it's convenient to do so. Obviously, this can be tricky, because if you have (String,int,int) You probably don't want to do (int,int,String) or (int,String,int) ALSO. Best to keep it to just one.
你是对的,iii 通常不会提出强有力的案例。通常,有必要保持强类型化,如下所示
等。
You are right, iii does not make a strong cases usually. Typically, it is necessary to keep things strongly typed as show below
etc.
这似乎有点毫无意义,在很多情况下,我可以理解为什么有些人可能只是简单地打乱参数序列以支持重载,而实际上他们只是设计得很糟糕的代码。然而,在某些情况下它是完全有道理的。
大多数程序员会选择某些参数序列,因为这些参数在特定顺序中更有意义,或者因为顺序实际上对某些计算的结果至关重要。以这些重载方法为例:
正如您在数学课上很早就学到的那样,用一个值求另一个值是一种非交换运算(即 2^3 != 3^2)。
因此,在这个例子中,每个方法都会通过另一个方法来提高一些数值。第一个参数始终是要由第二个参数给出的值引发的值(顺序很重要)。但是,正如您所看到的,参数列表的每个参数都可以由 String 或 int 类型表示。然而,操作的语义保持不变。
当然,出于显而易见的原因,这是一个非常人为的示例,但您可以看到原则上它是合理的。
我确信如果我多给它一点,我可以想出一个更好的例子,其中参数是某种特殊类型,这种事情更有意义。
It may seem somewhat pointless and in a lot of cases I can see why some people may simply shuffle parameter sequences around simply to support overloading where really they just have poorly designed code. However, it in some circumstances it make perfect sense.
Most programmers will choose certain parameter sequences based on a notion that such parameters make more sense in a particular order or because order is in-fact fundamentally important to the outcome of some calculation. Take these overloaded methods as an example:
As you learned very early on in math class, raising one value by another is a non-commutative operation (i.e. 2^3 != 3^2).
So in this example, each method will raise some numeric value by another. The first parameter is always the value that is intended to be raised by the value given as second parameter (order is important). However, as you can see, each argument to the parameter list may be represented by a String or an int type. The semantics of the operation however remains the same.
Of course this is a very contrived example for obvious reasons, but you can see how in principle it is reasonable.
I'm sure if i gave it a bit more though I could come up with a better example where the parameters are of some special type where this sort of thing makes even more sense.
参数列表由参数的数量和类型决定。因此,如果您的参数具有不同的类型,则对参数重新排序会产生不同的重载,因为编译器会在不同的槽中看到不同的类型。
这两个函数都有两个参数,但类型不匹配,因此它们是有效的重载。
至于为什么要这样做,通常情况下参数的顺序很重要。在我维护的代码库中,我们有一些异常,这些异常可能有原因、消息和其他参数。所以下面的两个调用是不一样的:
第一种情况
cause
是异常的原因,message
是要显示的消息,而record 是消息的参数。在第二种情况下,
cause
和recordName
都被解释为消息的参数。在第三种情况下,没有原因,在第四种情况下,没有原因,而且message
参数处于错误的位置,并且不会被正确处理。这是通过对 ABCException 构造函数进行几个有用的重载来实现的(尽管在本例中我们使用可变参数来支持无限数量的参数)。
Parameter lists are determined by the number and types of the parameters. So if your parameters have different types, re-ordering the parameters gives a different overload because the compiler sees different types in different slots.
Both functions have two parameters but the types don't match so they are valid overloads.
As to why you might want to do this, it is often the case that the order of the parameters matters. In the codebase I maintain we have Exceptions that potentially have a cause, a message, and other parameters. So the following two calls are not the same:
In the first case
cause
is the cause of the exception,message
is the message to display, andrecord
is the parameter for the message. In the second case bothcause
andrecordName
are interpreted as parameters for the message. In the third case there is no cause and in the fourth case there is no cause and furthermore themessage
argument is in the wrong position and won't be processed properly.This is accomplished by having several useful overloads of the ABCException constructor (though in this case we are using varargs to support unlimited numbers of parameters).