Перегрузка немного усложняет преобразование метода в функцию:
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)
}
Вы не можете выборочно импортировать один из набора перегруженных методов.
Существует большая вероятность того, что возникнет двусмысленность при попытке применить неявные представления для адаптации аргументов к типам параметров:
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
}
По отдельности эти причины не заставляют вас полностью избегать перегрузки. Я чувствую, что упускаю более серьезные проблемы.
ОБНОВЛЕНИЕ
Доказательства накапливаются.
ОБНОВЛЕНИЕ 2
ОБНОВЛЕНИЕ 3
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...
Я думаю, что этот совет не предназначен специально для scala, а для OO в целом (пока я знаю, что scala должен быть лучшим в своем классе между ОО и функционалом).
Переопределение - это нормально, это суть полиморфизма и центральное место в объектно-ориентированном дизайне.
С другой стороны, перегрузка более проблематична. При перегрузке методов трудно понять, какой метод действительно будет вызван, и это действительно часто является источником путаницы. Также редко есть оправдание, почему перегрузка действительно необходима. В большинстве случаев проблему можно решить другим способом, и я согласен с тем, что перегрузка - это запах.
Вот статья , которая хорошо объясняет, что я имею в виду под «перегрузкой - источником путаницы», что, я думаю, является основной причиной, по которой это не рекомендуется. Это для java, но я думаю, что это применимо и к scala.
Причины, которые приводят Гилад и Джейсон (ретроним), - все это очень веские причины избегать перегрузки, если это возможно. Причины Гилада сосредоточены на том, почему перегрузка в целом проблематична, тогда как причины Джейсона сосредоточены на том, почему это проблематично в контексте других функций Scala.
К списку Джейсона я бы добавил, что перегрузка плохо взаимодействует с выводом типа. Рассмотрим:
val x = ...
foo(x)
Изменение предполагаемого типа x
может изменить вызываемый метод foo
. Значение x
не нужно изменять, только предполагаемый тип x
, что может произойти по разным причинам.
По всем указанным причинам (и некоторым другим, я уверен, что я забываю), я считаю, что перегрузку методов следует использовать как можно реже.