为什么方法签名中不包含返回类型的方法?

时间:2012-11-09 19:04:33

标签: java

为什么返回类型的方法不包含在签名中?

一个例子

public void method1(String arg){...}

public String method1(String arg){...}

会导致错误。

10 个答案:

答案 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)

在设计重载解析等问题时,需要考虑几点。

在退货类型上省略重载的原因:

  1. 简化忽略函数返回值(就像人们经常使用错误代码一样)。
  2. 使程序更容易为人类读者消化。特别是,这就是Python中它们根本没有函数重载的原因。 (品味问题)
  3. C遗产。当语言来自C系列而设计师并不认为某些事情是重要的事情时,它就会一如既往地留下......
  4. 在返回类型上添加重载的原因:

    1. 难以忽略返回的值。这可能很方便并节省了一些打字,但有一天肯定会咬你。
    2. 表现力(当然与易消化相反:))。你有没有想写int x = json.get("int_value"); float y = json.get("float_value");之类的东西?在某些语言(如C ++)中仍然可以使用代理和强制转换运算符实现,但返回类型的重载会更容易。
    3. 表现性。每次传递retun值作为函数的引用只是为了重用它的资源,这可能是返回类型的重载(使用类似的隐藏参数)。考虑string s; getline(cin, s); vs string s = getline(cin);。这就是表达性与参考透明度以及最终易于代码消化的结合。
    4. 现在回到你的问题'为什么?'。既然你在询问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)

根据参数的数量和类型检查方法重载,而不是基于返回类型。这就是你得到错误的原因。