Почему «избегать перегрузки метода»? - PullRequest

Ответы [ 3 ]

103 голосов
/ 25 марта 2010

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

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 
}

По отдельности эти причины не заставляют вас полностью избегать перегрузок. Я чувствую, что мне не хватает некоторых больших проблем.

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...
8 голосов
/ 27 марта 2010

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

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

val x = ...
foo(x)

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

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

1 голос
/ 24 марта 2010

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

Переопределение отлично, это сердце полиморфизма и является центральным элементом дизайна ОО.

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

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

...