为啥重载的scala函数需要返回类型?

Posted

技术标签:

【中文标题】为啥重载的scala函数需要返回类型?【英文标题】:Why is return type needed on overloaded scala function?为什么重载的scala函数需要返回类型? 【发布时间】:2014-04-09 05:22:51 【问题描述】:
  def toJson[T](obj: T) = 
      gson.toJson(obj)
  

  def toJson[T](list: Seq[T]) = 
      toJson(seqAsJavaList(list))
  

这不会编译。这被记录为一项功能 (see this answer):

当一个方法被重载并且其中一个方法调用另一个方法时。调用方法需要一个返回类型注解。

问题是:为什么?

从上面的链接+同事的一些额外想法,可能的原因如下:

scala 也使用返回类型来确定重载方法。是这样吗,为什么需要它? (例如,Java 不使用返回类型) 偏函数 - 如果其中一个方法没有参数而另一个有参数,则 toJson() 可能会被视为偏函数,因此无法确定返回类型是 String 还是 Function

我知道任何人都指定返回类型是最佳实践,但为什么实际上上面的 sn-p 没有编译,如果返回类型推断不够好,为什么一开始就在那里?

【问题讨论】:

你的意思是让第二个也给gson打电话吗?正如它所写的那样,它是无限递归的。 @barnesjd : 如果 seqAsJavaList 有任何迹象,那不是 - java.util.List 不是 Seq[T] 哦,对了……在这种情况下,它调用了另一个函数,这是他的问题。谢谢 @TheTerribleSwiftTomato 在范围内具有隐式转换,调用可以是递归的;当您知道预期的类型时,在重载分辨率之后应用转换,即,您无法先验地(在推理之前)告诉您打算使用哪种方法。这是重载罪恶的炼狱。 @som-snytt :我知道,因此我的回答(完整披露,以防万一:只有 last 句子是添加after您的评论已发布:) )。 【参考方案1】:

可能不是主要原因,但请注意,显式参数的另一个原因如下:

当一个方法是递归的。

问题是,根据“调用”函数的返回类型,调用可以是对其同名的,也可以是对自身的调用(即递归)。

假设:

trait C

class A extends C

def a(obj: A) = 2

现在考虑:

def a[T <: C](obj: T): Int = 
 a(obj)


a(new A) //an Int, 2

对比:

def a[T <: C](obj: T): Any = 
 a(obj)


a(new A) //infinite recursion

由于推断递归函数的返回类型是有限时间不可判定的一般,推断“调用”函数的返回类型也是有限时间不可判定的一般 em>。

【讨论】:

以上是关于为啥重载的scala函数需要返回类型?的主要内容,如果未能解决你的问题,请参考以下文章

在重载时为啥不考虑函数的返回类型? [复制]

为啥函数不能被返回类型重载? [复制]

c++中重载输出操作符,为啥要返回引用

C++里面,为啥重载前++时不返回引用就不能连用?

Java - 为啥没有基于返回类型的方法重载?

c++中为啥赋值运算符重载返回类型是引用