web-dev-qa-db-ja.com

なぜ「メソッドのオーバーロードを避ける」のですか?

75
missingfaktor

オーバーロードにより、メソッドを関数に持ち上げるのが少し難しくなります。

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

オーバーロードされたメソッドのセットの1つを選択的にインポートすることはできません。

暗黙的なビューを適用して引数をパラメータータイプに適合させようとすると、あいまいさが生じる可能性が高くなります。

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

デフォルトのパラメータを静かに使用できなくすることがあります:

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

個人的には、これらの理由により、オーバーロードを完全に回避することはできません。もっと大きな問題を逃しているように感じます。

[〜#〜] 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...
104
retronym

GiladとJason(retroym)が与える理由は、可能な限り過負荷を回避する非常に良い理由です。 Giladの理由は、一般的に過負荷が問題になる理由に焦点を当てていますが、Jasonの理由は、他のScala機能のコンテキストで問題がある理由に焦点を当てています。

Jasonのリストに、オーバーロードは型推論との相互作用が不十分であると付け加えます。考慮してください:

val x = ...
foo(x)

推定されるx型の変更により、どのfooメソッドが呼び出されるかが変わる可能性があります。 xの-​​は変更する必要はありません。推測されるxのタイプだけです。これはあらゆる種類の理由で発生する可能性があります。

与えられたすべての理由(さらに忘れてしまったことはもう少しあります)のために、メソッドのオーバーロードはできる限り控えめに使用すべきだと思います。

8
Jorge Ortiz

アドバイスは、特にscala向けではありませんが、OO一般的には(これまでのところscalaはOO and functional)の間で最高の組み合わせになるはずです。

Overridingは問題ありません。これは多型の中心であり、OO design。

一方で、オーバーロードはより問題があります。メソッドのオーバーロードでは、どのメソッドが実際に呼び出されるかを見分けるのが難しく、実際に頻繁に混乱の原因になります。また、オーバーロードが実際に必要な理由もめったにありません。ほとんどの場合、問題は別の方法で解決でき、過負荷は臭いであることに同意します。

ここに 記事 があります。これは「オーバーロードは混乱の原因です」と私が言っていることをうまく説明します。 Javaの場合ですが、scalaにも適用されると思います。

1
ewernli