ret*_*nym 105

重载使得将方法提升到函数有点困难:

object A {
   def foo(a: Int) = 0
   def foo(b: Boolean) = 0
   def foo(a: Int, b: Int) = 0

   val function = foo _ // fails, must use = foo(_, _) or (a: Int) => foo(a)
}
Run Code Online (Sandbox Code Playgroud)

您无法有选择地导入一组重载方法中的一个.

尝试应用隐式视图以使参数适应参数类型时,出现歧义的可能性更大:

scala> implicit def S2B(s: String) = !s.isEmpty                             
S2B: (s: String)Boolean

scala> implicit def S2I(s: String) = s.length                               
S2I: (s: String)Int

scala> object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }
<console>:15: error: ambiguous reference to overloaded definition,
both method foo in object test of type (b: Boolean)Int
and  method foo in object test of type (a: Int)Int
match argument types (java.lang.String)
       object test { def foo(a: Int) = 0; def foo(b: Boolean) = 1; foo("") }
Run Code Online (Sandbox Code Playgroud)

它可以安静地呈现默认参数不可用:

object test { 
    def foo(a: Int) = 0; 
    def foo(a: Int, b: Int = 0) = 1 
}
Run Code Online (Sandbox Code Playgroud)

单独地,这些原因并不会迫使您完全避免超载.我觉得我错过了一些更大的问题.

UPDATE

证据正在堆积.

更新2

  • 您不能(当前)在包对象中使用重载方法.
  • 适用性错误更难以诊断 API的调用者.

更新3

  • 静态重载解析可以抢夺所有类型安全的API:
scala> object O { def apply[T](ts: T*) = (); def apply(f: (String => Int)) = () }
defined object O

scala> O((i: String) => f(i)) // oops, I meant to call the second overload but someone changed the return type of `f` when I wasn't looking...
Run Code Online (Sandbox Code Playgroud)

  • 类型目前[由于缺乏一流的联合类型而无法普遍使用](https://issues.scala-lang.org/browse/SUGGEST-22?focusedCommentId=65935#comment-65935).是的,我在Scala的社区中看到了这种态度,但想象一下`addIntToDouble`,`addDoubleToInt`,即名称的笛卡尔积,而不是每个常见语义的静态类型.用命名替换打字似乎是倒退的.[Java得到了更多的东西](http://programmers.stackexchange.com/questions/176665/generics-and-type-erasure/212038#212038)也许我们认识到了. (3认同)
  • 目前,scalac中还存在一个错误,在某些情况下会由于重载而触发.https://issues.scala-lang.org/browse/SI-7596. (2认同)
  • 前两个问题不会影响重载的每个有效使用.提交[错误报告](https://issues.scala-lang.org/browse/SI-7856)第3期.[默认限制是选择](http://stackoverflow.com/a/4652681/615784),理论上可以修复.`_.foo`问题的错误是Scala的有限类型推断,而不是重载.你回答这个问题,但有些原因是由于Scala中的其他弱点可以改进.重载比运行时向下转换析取效率更高,或者笛卡尔名称产品嘈杂并且与共享语义断开连接. (2认同)
  • [我写的](https://groups.google.com/d/msg/scala-debate/m6QuiSUP43A/Kpys2dVGSNcJ)在讨论主题中(我之前评论中提到的错误报告),"IMO期待的是什么邪恶重载是不是,或者减少了为一个共同语义命名的重要性". (2认同)
  • 答案和评论对我来说似乎很幼稚,并且没有提到使用重载的一个最重要的原因:当一个方法实际上必须根据传递给它的类型执行非常不同的内部逻辑时。“使用隐式”的答案立即失败,因为可能不存在从一个对象到体现专用逻辑的不同类型的任何可能转换。 (2认同)

Jor*_*tiz 8

如果可能的话,Gilad和Jason(反语)给出的原因都是避免超载的理由.吉拉德的理由集中在为什么一般会出现重载问题,而杰森的理由则集中在为什么它在其他Scala功能的背景下存在问题.

对于Jason的列表,我想补充一点,重载与类型推断的交互性很差.考虑:

val x = ...
foo(x)
Run Code Online (Sandbox Code Playgroud)

推断类型的x更改可能会改变foo调用哪个方法.该x需求不会改变,只是推断类型的x,这可能发生的各种原因.

由于给出的所有原因(还有一些我确定我忘记了),我认为方法重载应该尽可能少地使用.

  • 如果您不希望发生这种情况,请声明x的类型.如果你没有宣布它,那么你说你希望改变它.对于具有相同参数数量的每个重载,`foo`的语义应该相同,否则它的设计不正确.至于限制奇异级联推理变更的范围,公共方法应该总是声明它们的返回类型.我认为这是影响版本之间Scala二进制兼容性的问题之一. (2认同)