Ну, это неоднозначно. Я полагаю, что семантика Java допускает это, и это может стоить запроса на применение семантики Java в Scala.
Источник неоднозначности заключается в следующем: параметр vararg может получить любое количество аргументов, включая 0. Поэтому, когда вы пишете thenReturn("a")
, вы хотите вызвать thenReturn
, который получает один аргумент, или сделать Вы хотите вызвать thenReturn
, который получает один объект плюс vararg, передавая 0 аргументов vararg?
Теперь, что происходит с такими вещами, Scala пытается найти, какой метод является «более конкретным». Любой, кто интересуется деталями, должен посмотреть это в спецификации Scala, но вот объяснение того, что происходит в данном конкретном случае:
object t {
def f(x: AnyRef) = 1 // A
def f(x: AnyRef, xs: AnyRef*) = 2 // B
}
если вы позвоните f("foo")
, то и А, и В
применимы. Какой из них больше
конкретный?
- можно вызвать B с параметрами типа
(AnyRef)
, поэтому A
так же конкретно, как B.
- можно вызвать A с параметрами типа
(AnyRef,
Seq[AnyRef])
благодаря кортежу
преобразование Tuple2[AnyRef,
Seq[AnyRef]]
соответствует AnyRef
. Так
B так же специфичен, как и А. Поскольку оба
так же, как и другие,
ссылка на f неоднозначна.
Что касается «преобразования кортежей», то это один из самых малоизвестных синтаксических сахаров в Scala. Если вы делаете вызов f(a, b)
, где a
и b
имеют типы A
и B
, и f
не принимает (A, B)
, но есть f
, который принимает (Tuple2(A, B))
тогда параметры (a, b)
будут преобразованы в кортеж.
Например:
scala> def f(t: Tuple2[Int, Int]) = t._1 + t._2
f: (t: (Int, Int))Int
scala> f(1,2)
res0: Int = 3
Теперь при вызове thenReturn("a")
преобразование кортежей не происходит. Это не проблема. Проблема в том, что, учитывая возможность преобразования кортежей, ни одна из версий thenReturn
не является более конкретной, поскольку любой параметр, передаваемый одному, может передаваться и другому.