Хотя могут быть допустимые случаи, когда такие перегрузки методов могут стать неоднозначными, почему компилятор запрещает код, который не является неоднозначным ни во время компиляции, ни во время выполнения?
Пример:
// This fails:
def foo(a: String)(b: Int = 42) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// This fails, too. Even if there is no position in the argument list,
// where the types are the same.
def foo(a: Int) (b: Int = 42) = a + b
def foo(a: String)(b: String = "Foo") = a + b
// This is OK:
def foo(a: String)(b: Int) = a + b
def foo(a: Int) (b: Int = 42) = a + b
// Even this is OK.
def foo(a: Int)(b: Int) = a + b
def foo(a: Int)(b: String = "Foo") = a + b
val bar = foo(42)_ // This complains obviously ...
Есть ли причины, по которым эти ограничения нельзя ослабить немного?
Особенно, когда преобразование сильно перегруженного кода Java в аргументы Scala по умолчанию очень важно, и после замены большого количества методов Java одним методом Scala не очень удобно выяснять, что спецификация / компилятор накладывает произвольные ограничения.
object Test { def a[A](b: Int, c: Int, d: Int = 7): Unit = {}; def a[A](a:String, b: String = ""): Unit = {}; a(2,3,4); a("a");}
Ответы:
Я хотел бы привести слова Лукаса Ритца ( отсюда ):
Решением для будущей версии Scala может быть включение имен типов аргументов не по умолчанию (те, которые находятся в начале метода, которые устраняют неоднозначность перегруженных версий) в схему именования, например, в этом случае:
это было бы что-то вроде:
Кто-то готов написать предложение SIP ?
источник
A with B
, например?Было бы очень трудно получить четкую и точную спецификацию для взаимодействия разрешения перегрузки с аргументами по умолчанию. Конечно, для многих отдельных случаев, подобных представленному здесь, легко сказать, что должно произойти. Но этого недостаточно. Нам нужна спецификация, которая решает все возможные варианты. Разрешение перегрузки уже очень сложно определить. Добавление аргументов по умолчанию в смесь усложнит ситуацию. Вот почему мы решили разделить их.
источник
Я не могу ответить на ваш вопрос, но вот обходной путь:
Если у вас есть два очень длинных списка аргументов, которые отличаются только одним аргументом, это может стоить проблем ...
источник
Either
а не только дляfoo
этого - всякий раз, когдаEither[A, B]
запрашивается значение, обаA
иB
принимаются. Вместо этого следует определить тип, который принимается только функциями, имеющими аргументы по умолчанию (какfoo
здесь), если вы хотите пойти в этом направлении; конечно, становится еще менее понятно, является ли это удобным решением.Для меня сработало переопределение (в стиле Java) методов перегрузки.
Это гарантирует компилятору, какое разрешение вы хотите в соответствии с существующими параметрами.
источник
Вот обобщение ответа @Landei:
Что вы действительно хотите:
Workarround
источник
Один из возможных сценариев
Компилятор будет сбит с толку о том, какой из них вызывать. Во избежание других возможных опасностей компилятор допускает, что максимум один перегруженный метод имеет аргументы по умолчанию.
Просто мое предположение :-)
источник
Насколько я понимаю, в скомпилированных классах могут быть конфликты имен со значениями аргументов по умолчанию. Я видел что-то подобное в нескольких темах.
Спецификация именованного аргумента находится здесь: http://www.scala-lang.org/sites/default/files/sids/rytz/Mon,%202009-11-09,%2017:29/named-args.pdf
Здесь утверждается:
Так что пока, во всяком случае, это не сработает.
Вы можете сделать что-то вроде того, что вы можете сделать в Java, например:
источник