为什么返回类型的方法不包含在签名中?
一个例子
public void method1(String arg){...}
public String method1(String arg){...}
会导致错误。
答案 0 :(得分:32)
这样做是因为编译器无法找出所有上下文中的重载。
例如,如果你打电话
String x = method1("aaa");
编译器知道您正在寻找第二个重载。但是,如果你打电话
method1("aaa");
像这样,编译器不知道你想要调用哪两个方法,因为调用返回String
的方法并丢弃结果是可以的。为避免这种歧义,Java禁止仅在返回类型上有所不同的重载。
答案 1 :(得分:4)
由于您的问题并未解决标题中的任何特定编程语言(我知道它在标记中),我将与 Swift 分享我最近的经验。 在 Swift 函数/方法签名中实际包含返回类型。因此,只有在没有显式指定返回类型的情况下调用此函数/方法时,编译器才会抛出错误,例如:
func some() -> Bool {
return true;
}
func some() -> Int {
return 1;
}
let valBool: Bool = some()
let valInt: Int = some()
// this doesn't work: Ambiguous use of 'some'
some()
除此之外,Swift甚至让它变得更有趣。它允许您拥有2个具有相同参数的函数/方法,并且只有在参数名称不同时才返回类型,例如:
func some(#foo: Bool) -> Bool {
return foo;
}
func some(#bar: Bool) -> Bool {
return bar;
}
some(foo: true)
some(bar: false)
因此它在方法签名
中为您提供语义区分UPD。由于Swift 2.0外部参数名称已更改,现在您必须提供两次外部和本地名称,即使它们相同
func some(foo foo: Bool) -> Bool {
return foo;
}
func some(bar bar: Bool) -> Bool {
return bar;
}
some(foo: true)
some(bar: false)
答案 2 :(得分:3)
您不能仅对其返回类型重载方法。这完全是非法的。让我们暂时假设使用返回类型的重载方法是合法的,并且您定义了两个method1
方法。现在我们要调用返回String object
:
String string = method1(sth);
JVM理论上可以识别你想要调用的方法,但是这样的调用呢:
method1(sth);
正如您所看到的,可以调用这两种方法,并且这些操作是明确的。 JVM不知道它应该调用哪个方法。这就是禁止这种超载的原因。
答案 3 :(得分:2)
因为在这种情况下无法解决应该调用哪个重载方法:
public static void main(String... args) {
method1("aaa");
}
答案 4 :(得分:1)
在设计重载解析等问题时,需要考虑几点。
在退货类型上省略重载的原因:
在返回类型上添加重载的原因:
int x = json.get("int_value"); float y = json.get("float_value");
之类的东西?在某些语言(如C ++)中仍然可以使用代理和强制转换运算符实现,但返回类型的重载会更容易。string s; getline(cin, s);
vs string s = getline(cin);
。这就是表达性与参考透明度以及最终易于代码消化的结合。现在回到你的问题'为什么?'。既然你在询问Java,那么答案显然是因为James重视忽略返回类型重载的理由而不是将它们包含在语言中。
答案 5 :(得分:1)
我自己在某个时候也遇到过同样的问题,虽然我可以看到当您不将返回值分配给适当类型的变量时,编译器将如何不知道要调用哪个函数,为什么还要抛出功能级别上的错误?为什么不调用函数呢?基本上,一旦您承诺让签名仅在返回值上有所不同,就必须确保以这种方式使用它们,然后,只有这样,编译器才会抱怨。当然,要使它与严格的单遍编译器一起使用可能需要花费一些额外的工作,但我认为它可以实现。
答案 6 :(得分:0)
您可以将函数作为过程调用:method1("arg");
其中method1是列表中的第二个方法(String method1(String arg){}
)。然后编译器将无法将其与第一个(void method1(String arg){}
)区分开来。
答案 7 :(得分:0)
编译器负责方法绑定。每当遇到methodName()时,它都必须绑定到某些方法定义,这时它可能不知道方法的返回类型。因此方法返回类型不包括在方法签名中。编译器根据方法签名绑定方法。
答案 8 :(得分:0)
当编译器遇到方法调用时。它将方法调用静态绑定到定义的方法之一。 让我们看看如果返回类型包含在方法签名中会发生什么
class Example{
public void method1(String arg){ return arg}
public String method1(String arg){}
public static void main(String[] args){
Example e = new Example();
e.method1("abc");
}
}
e.method1("abc") 如果方法签名中包含返回类型,编译器将不知道绑定到哪个方法。
答案 9 :(得分:-1)
根据参数的数量和类型检查方法重载,而不是基于返回类型。这就是你得到错误的原因。