Почему scalac использует метод Java vararg вместо единственного аргумента

1

Мы используем Elasticsearch в качестве базы данных и на основе определения я создаю сопоставление типов. Это сопоставление - это в основном объект JSON, который XContentBuilder с помощью XContentBuilder Java-API elasticsearch.

В моем файле scala я определил объект Enumeration, который содержит возможные типы данных elasticsearch, например:

object TypeMapping extends Enumeration {

    val StringType = DataType("string")
    val FloatType = DataType("float")
    ...
    val GeoShapeType = DataType("geo_shape")
    val AttachmentType = DataType("attachment")

    final case class DataType(esType: String) extends Val {
        override def toString: String = esType
    }
}

Теперь, когда я использую это при создании отображения JSON следующим образом:

val builder = jsonBuilder.startObject("name").field("type", StringType).endObject

компилятор scala прекрасно справляется со всеми способами вызова; нет ошибок или предупреждений.

Метод field перегружено, каждый прием String параметр name и параметр value. Эти значения могут быть конкретными (String, int, int[] и т.д.) Или vararg (String..., int... и т.д.), Но также вариант Object для конкретных вызовов и vararg.

Теперь я бы ожидал, что компилятор scala выберет field(String name, Object value) в случае, который я описываю здесь, но, к моему удивлению, я нахожу, что field(String name, Object... value) вызывается,

Я не понимаю, почему это происходит. Может ли кто-нибудь объяснить это мне?

  • 0
    Откуда ты знаешь, что выбирает метод varargs. Что происходит, чтобы показать это?
  • 0
    Результирующий объект JSON отличается. Вызов vararg создает значение поля Array, в то время как non-vararg создает значение поля String. Я только что опубликовал свой частичный код, объясняющий, какие API-вызовы я делаю. Вы также можете воспроизвести это, создав файл класса Java с двумя методами печати, который вызывается, и вызывая его в классе Scala.
Показать ещё 1 комментарий
Теги:
elasticsearch
variadic-functions

1 ответ

1

Scala выбирает версию varargs как более конкретную, потому что (String, Array[Any]) можно применить к другому сигнатурному field(name: String, value: Any). (И не наоборот).

Учитывая, что оба метода находятся в одном классе, я не уверен, есть ли каноническое обходное решение помимо рефлексивного доступа:

  type Picker = {
    def f(name: String, value: Any): Int
  }
  Console println x.f("hi", "high")                // varargs
  Console println (x: Picker).f("hi", "high")      // not

неоднозначности:

public class JOver {
    public int f(String name, Object value) { return 1; }
    public int f(String name, Object... values) { return 2; }
}
  • 0
    Я звоню Java API из Scala здесь. StringType будет выглядеть как тип Any , который я угадал, и который я ожидал отобразить в типе java.lang.Object , но если я правильно вас понял, он будет отображаться как Array[Any] и, следовательно, отображается в java.lang.Object... ?
  • 0
    Я не пользователь, но проверил этот сигнал в XContentBuilder. Разрешение перегрузки в Scala просто смотрит на признаки методов, которые применяются к вашим аргументам. Массив - это Объект, но не наоборот.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню