Подтвердить что ты не робот

Scala: Конструктор, выполняющий либо Seq, либо varargs

Я предполагаю, что по соображениям совместимости тип параметров vararg Any* - Array [Any] - пожалуйста, исправьте это, если я ошибаюсь. Однако это не объясняет следующую ошибку:

class Api(api_url: String, params: Seq[(String, String)]) {
  def this(api_url: String, params: (String, String)*)
    = this(api_url, params.seq)
}

Этот код не компилируется, но дает предупреждение:

двойное определение: конструктор Api: (api_url: String, params: (String, String) *) Api и конструктор Api: (api_url: String, params: Seq [(String, String)]) Api в строке 13 имеет один и тот же тип после стирания: (api_url: java.lang.String, params: Seq) Api

Итак, как мне определить конструктор, берущий либо varargs, либо последовательность?

4b9b3361

Ответ 1

Метод, принимающий varargs, также всегда принимает последовательность, поэтому нет необходимости определять вспомогательный конструктор или перегруженный метод.

Учитывая

class Api(api_url: String, params: (String, String)*)

вы можете называть это следующим образом

new Api("url", ("a", "b"), ("c", "d"))

или

val seq = Seq(("a", "b"), ("c", "d"))
new Api("url", seq:_*)

Кроме того, в вашем вопросе вы вызываете метод seq для параметра params. Вероятно, это не так, как вы планировали. seq используется для обеспечения того, чтобы операции с результирующей коллекцией выполнялись последовательно, а не параллельно. Этот метод был введен с параллельными наборами в версии 2.9.0 Scala.

То, что вы, вероятно, хотели использовать, было toSeq, которое возвращает коллекцию, которую он использует при преобразовании в Seq (или сам, если он уже является Seq). Но поскольку параметры varargs уже введены как Seq, это все равно no-op.

Ответ 2

Нет: фактически, Any* фактически почти идентичен Seq[Any], а не Array[Any].

Чтобы устранить двусмысленность между ними, вы можете использовать этот метод, чтобы добавить фиктивный неявный параметр, чтобы сделать подпись отличной:

class Api(api_url: String, params: Seq[(String, String)]) {
  def this(api_url: String, params: (String, String)*)(implicit d: DummyImplicit) =
    this(api_url, params)
}

Ответ 3

Я предполагаю, что вы хотите, чтобы метод вызывал более симпатичный, и поэтому явный вызов с помощью _* не является опцией. В этом случае вы можете решить проблему с перегрузкой метода.

class Api(api_url: String, params: Seq[(String, String)]) {
  def this(api_url: String, param : (String, String), params: (String, String)*)
    = this(api_url, param +: params)
  def this(api_url: String)
    = this(api_url, Seq())
}