scala 为什么“避免方法重载”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2510108/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 02:01:28  来源:igfitidea点击:

Why "avoid method overloading"?

scalaoverloading

回答by retronym

Overloading makes it a little harder to lift a method to a function:

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

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)
}

You cannot selectively import one of a set of overloaded methods.

您不能有选择地导入一组重载方法中的一个。

There is a greater chance that ambiguity will arise when trying to apply implicit views to adapt the arguments to the parameter types:

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

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("") }

It can quietly render default parameters unusable:

它可以悄悄地使默认参数不可用:

object test { 
    def foo(a: Int) = 0; 
    def foo(a: Int, b: Int = 0) = 1 
}

Individually, these reasons don't compel you to completely shun overloading. I feel like I'm missing some bigger problems.

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

UPDATE

更新

The evidence is stacking up.

证据越来越多。

UPDATE 2

更新 2

  • You can't (currently) use overloaded methods in package objects.
  • Applicability errors are harder to diagnosefor callers of your API.
  • 您不能(当前)在包对象中使用重载方法。
  • 对于 API 的调用者来说,适用性错误更难诊断

UPDATE 3

更新 3

  • static overload resolution can rob an API of all type safety:
  • 静态重载解析可以抢夺所有类型安全的 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...

回答by Jorge Ortiz

The reasons that Gilad and Jason (retronym) give are all very good reasons to avoid overloading if possible. Gilad's reasons focus on why overloading is problematic in general, whereas Jason's reasons focus on why it's problematic in the context of other Scala features.

Gilad 和 Jason(retronym)给出的理由都是尽可能避免超载的很好的理由。Gilad 的原因集中在为什么重载通常会出现问题,而 Jason 的原因集中在为什么它在其他 Scala 特性的上下文中会出现问题。

To Jason's list, I would add that overloading interacts poorly with type inference. Consider:

在 Jason 的列表中,我要补充一点,重载与类型推断的交互很差。考虑:

val x = ...
foo(x)

A change in the inferred type of xcould alter which foomethod gets called. The valueof xneed not change, just the inferred type of x, which could happen for all sorts of reasons.

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

For all of the reasons given (and a few more I'm sure I'm forgetting), I think method overloading should be used as sparingly as possible.

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

回答by ewernli

I think the advice is not meant for scala especially, but for OO in general (so far I know scala is supposed to be a best-of-breed between OO and functional).

我认为这个建议并不是特别针对 scala,而是针对一般的面向对象(到目前为止,我知道 Scala 应该是面向对象和函数式之间的最佳组合)。

Overridingis fine, it's the heart of polymorphism and is central to OO design.

覆盖很好,它是多态的核心,也是面向对象设计的核心。

Overloadingon the other hand is more problematic. With method overloading it's hard to discern which method will be really invoked and it's indeed a frequently a source of confusion. There is also rarely a justification why overloading is really necessary. The problem can most of the time be solved another way and I agree that overloading is a smell.

另一方面,重载更成问题。使用方法重载很难辨别哪个方法将被真正调用,这确实经常引起混淆。也很少有理由说明为什么真正需要重载。大多数情况下,问题可以通过另一种方式解决,我同意超载是一种气味。

Here is an articlethat explain nicely what I mean with "overloading is a source of confusion", which I think is the prime reason why it's discouraged. It's for java but I think it applies to scala as well.

这里有一篇文章很好地解释了我的意思“重载是混乱的根源”,我认为这是不鼓励它的主要原因。它适用于 Java,但我认为它也适用于 Scala。