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, либо последовательность?
Ответы
Ответ 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())
}