Java - 为什么没有基于返回类型的方法重载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2744511/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java - why no return type based method overloading?
提问by llm
I know this is not possible but can anyone provide a theory as to why Java chose not to support this? I am asking because I just ran into a situation where I thinkit would be nice to have.
我知道这是不可能的,但谁能提供一个理论来解释为什么 Java 选择不支持这一点?我问是因为我刚刚遇到了一种情况,我认为有这种情况会很好。
采纳答案by Péter T?r?k
Because you are not required to capture the return value of a method in Java, in which case the compiler can not decide which overload to use. E.g.
因为在 Java 中不需要捕获方法的返回值,在这种情况下编译器无法决定使用哪个重载。例如
boolean doSomething() { ... }
int doSomething() { ... }
doSomething(); // which one to call???
回答by Tadeusz Kopec
It's because you are free to ignore return value.
这是因为您可以随意忽略返回值。
回答by Michael Aaron Safyan
While it is theoretically possible, it was not used in Java for the same reason it wasn't used in C++; namely, it has been found that overloads based on return-types are generally more confusing to developers, the benefit is marginal compared with the costs of implementing it, and it would be ambiguous in the case where the return-type is not assigned to a value. For those reasons return-type based overloading is not supported.
虽然理论上可行,但在 Java 中并未使用,原因与在 C++ 中未使用的原因相同;也就是说,已经发现基于返回类型的重载通常更容易让开发人员感到困惑,与实现它的成本相比,收益是微不足道的,如果返回类型没有分配给一个价值。由于这些原因,不支持基于返回类型的重载。
回答by Summer_More_More_Tea
I think one of the reasons is that, in most case you can determine the return type of a function only after the execution of the function instead of before this process. Thus, it can not help you decide which overloaded function to invoke just based on different return types of functions.
我认为原因之一是,在大多数情况下,您只能在函数执行之后而不是在此过程之前才能确定函数的返回类型。因此,仅仅根据不同的函数返回类型并不能帮助您决定调用哪个重载函数。
回答by Jay
I've wondered why they don't support this also. Sure, if you ignore the return value, the compiler would have no way to know which you wanted. But that's the same ambiguity that arises with passing nulls. Like:
我想知道为什么他们也不支持这一点。当然,如果您忽略返回值,编译器将无法知道您想要哪个。但这与传递空值时产生的歧义相同。喜欢:
String doSomething(String s) { ... }
String doSomething(Integer s) { ... }
...
String out=doSomething(null);
In this case, the compiler just complains that the call is ambiguous, and you have to resolve it by casting the null, like:
在这种情况下,编译器只是抱怨调用不明确,您必须通过转换 null 来解决它,例如:
String out=doSomething((String)null);
You could do the same thing with overloading by return type:
您可以通过返回类型重载来做同样的事情:
String getSomething() { ... }
Integer getSomething() { ... }
...
Integer n=getSomething();
would presumably call the second function.
大概会调用第二个函数。
getSomething();
would be ambiguous (and in this example, probably useless, unless it had side effects, but that's another story), so you'd have to say:
将是模棱两可的(在这个例子中,可能没用,除非它有副作用,但那是另一回事),所以你必须说:
(String) getSomething();
More realistically, perhaps:
更现实的是,也许:
if ((String) getSomething()==null) ...
But that's the easy case. I can see a compiler-writer not wanting to support this because it could get very complicated to figure out in anything other than a simple assignment. For example, consider:
但这是简单的情况。我可以看到编译器编写者不想支持这一点,因为除了简单的赋值之外,要弄清楚任何事情都会变得非常复杂。例如,考虑:
String getSomething() { ... };
Integer getSomething() { ... };
String getOtherthing() { ... };
...
if (getSomething().equals(getOtherthing())) ...
The compiler would have to figure out that both String and Integer have equals functions, so either one is valid at that point. Then it would have to notice that getOtherthing is a String, and Integer.equals(String) is unlikely, so probably what the writer wanted was String.equals(String). Do-able, but at that point I'm starting to see that in the general case, this could be a beast.
编译器必须弄清楚 String 和 Integer 都具有 equals 函数,因此在这一点上任何一个都是有效的。然后它必须注意到 getOtherthing 是一个字符串,而 Integer.equals(String) 不太可能,所以作者想要的可能是 String.equals(String)。可行,但在那一点上,我开始看到在一般情况下,这可能是一头野兽。
And then suppose we add:
然后假设我们添加:
Integer getOtherthing() { ... };
Now what does the compiler do with that IF statement? It could use the String versions of both functions, or the Integer, but not the String of one and the Integer of the other. At that point it would have to insist on a cast to tell it which, I guess. But the complexity is really getting out of hand.
现在编译器如何处理那个 IF 语句?它可以使用两个函数的字符串版本或整数,但不能使用一个的字符串和另一个的整数。到那时,我想它必须坚持让演员告诉它哪个。但复杂性真的失控了。
And if it's hard for the compiler to figure out what you really mean, imagine what it would be like for another programmer who can't look up all the function signatures as fast as the compiler can.
如果编译器很难弄清楚你真正的意思,想象一下对于另一个无法像编译器一样快地查找所有函数签名的程序员会是什么样子。
回答by Puyover
Because Java can cast the return type value to the target variable, so it doesn't know into what variable type are you storing the return value of the function.
因为Java可以将返回类型值强制转换为目标变量,所以它不知道你存储函数的返回值是什么变量类型。
回答by Lukas Eder
One interesting aspect about this question is the fact that the Java language forbids overloading methods only by return type. But not the JVM:
关于这个问题的一个有趣方面是 Java 语言禁止仅通过返回类型重载方法这一事实。但不是 JVM:
Note that there may be more than one matching method in a class because while the Java language forbids a class to declare multiple methods with the same signature but different return types, the Java virtual machine does not. This increased flexibility in the virtual machine can be used to implement various language features. For example, covariant returns can be implemented with bridge methods; the bridge method and the method being overridden would have the same signature but different return types.
请注意,一个类中可能有多个匹配的方法,因为 Java 语言禁止一个类声明多个具有相同签名但返回类型不同的方法,而 Java 虚拟机则没有。虚拟机中这种增加的灵活性可用于实现各种语言功能。例如,协变返回可以用桥接方法实现;桥接方法和被覆盖的方法将具有相同的签名但不同的返回类型。
回答by Saifullah Memon
overloading function only on the basis of return type is confusing for the compiler to distinguish between the calls, because at the time of invocation you are not giving the return type, as in the case with the parameters, so you only give the parameter list and this parameter list is the only way for the compiler to distinguish between the function calls, and return value is received at the completion of the function, that is why return type does not contributes to the signature of the function
仅根据返回类型重载函数对于编译器区分调用会造成混淆,因为在调用时您没有给出返回类型,就像在参数的情况下一样,因此您只给出了参数列表和这个参数列表是编译器区分函数调用的唯一方式,返回值是在函数完成时接收的,这就是为什么返回类型对函数的签名没有贡献的原因
回答by SARIKA
Method overloading uses compile time polymorphism technique. Method overriding uses run time polymorphism technique.
方法重载使用编译时多态技术。方法覆盖使用运行时多态技术。
Method overloading:
方法重载:
As said in previous answers, java does not support method overloading with different return type and same arguments. This is because, it has to determine which method to use at the compile time itself. To remove the ambiguity, they designed the method overloading technique like this.
正如之前的答案中所说,java 不支持具有不同返回类型和相同参数的方法重载。这是因为,它必须在编译时自己确定使用哪种方法。为了消除歧义,他们设计了这样的方法重载技术。
If we really need method overloading with different types and same arguments, it is possible to some extent with mehtod overriding.
如果我们真的需要使用不同类型和相同参数的方法重载,那么在某种程度上可以使用方法覆盖。
Method overriding:
方法覆盖:
Method overriding uses run-time polymorphism technique. Hence which method to execute is not decided at compile time and it is decided at run-time by JVM.
方法覆盖使用运行时多态技术。因此,执行哪种方法不是在编译时决定的,而是由 JVM 在运行时决定的。
With co-variant return types, we can have different return type in the sub class's method with same arguments as base class.
使用协变返回类型,我们可以在子类的方法中具有与基类相同的参数的不同返回类型。
Example of co-variant return type:
协变返回类型示例:
class BaseClass {
BaseClass dosomething(){
System.out.println("Print BaseClass");
return this;
}
}
class AnotherBaseClass extends BaseClass {
@Override
BaseClass dosomething(){
System.out.println("Print AnotherBaseClass");
return this;
}
}
class SubClass extends AnotherBaseClass {
@Override
SubClass dosomething(){ /*Here SubClass is co-vairantreturn type*/
System.out.println("Print SubClass");
return this;
}
public static void main(String args[]){
SubClass s1 = new SubClass();
s1.dosomething();
}
}
Output:
输出:
Print SubClass
打印子类