Почему “избегают перегрузки метода”?

3 ответа

Перегрузка немного усложняет преобразование метода в функцию:

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

  • Вы не можете (в настоящее время) использовать перегруженные методы в объектах пакета.
  • Ошибки применимости труднее диагностировать для вызывающих ваш 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...
105
ответ дан 24 November 2019 в 11:41
поделиться

Я думаю, что этот совет не предназначен специально для scala, а для OO в целом (пока я знаю, что scala должен быть лучшим в своем классе между ОО и функционалом).

Переопределение - это нормально, это суть полиморфизма и центральное место в объектно-ориентированном дизайне.

С другой стороны, перегрузка более проблематична. При перегрузке методов трудно понять, какой метод действительно будет вызван, и это действительно часто является источником путаницы. Также редко есть оправдание, почему перегрузка действительно необходима. В большинстве случаев проблему можно решить другим способом, и я согласен с тем, что перегрузка - это запах.

Вот статья , которая хорошо объясняет, что я имею в виду под «перегрузкой - источником путаницы», что, я думаю, является основной причиной, по которой это не рекомендуется. Это для java, но я думаю, что это применимо и к scala.

1
ответ дан 24 November 2019 в 11:41
поделиться

Причины, которые приводят Гилад и Джейсон (ретроним), - все это очень веские причины избегать перегрузки, если это возможно. Причины Гилада сосредоточены на том, почему перегрузка в целом проблематична, тогда как причины Джейсона сосредоточены на том, почему это проблематично в контексте других функций Scala.

К списку Джейсона я бы добавил, что перегрузка плохо взаимодействует с выводом типа. Рассмотрим:

val x = ...
foo(x)

Изменение предполагаемого типа x может изменить вызываемый метод foo . Значение x не нужно изменять, только предполагаемый тип x , что может произойти по разным причинам.

По всем указанным причинам (и некоторым другим, я уверен, что я забываю), я считаю, что перегрузку методов следует использовать как можно реже.

8
ответ дан 24 November 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: