scala types constructor variadic-functions

Scala: Constructor que toma Seq o varargs



types variadic-functions (3)

Supongo que, por razones de compatibilidad, el tipo de parámetros vararg Any* es Array [Any] - corríjalo si me equivoco. Sin embargo, esto no explica el siguiente error:

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

Este código no se compila, pero da la advertencia:

doble definición: constructor Api: (api_url: String, params: (String, String) *) Api y constructor Api: (api_url: String, params: Seq [(String, String)]) Api en la línea 13 tienen el mismo tipo después de borrar : (api_url: java.lang.String, params: Seq) Api

Entonces, ¿cómo defino un constructor tomando varargs o una secuencia?


No: en realidad, Any* es en realidad casi idéntico a Seq[Any] , no a Array[Any] .

Para desambiguar entre los dos, puede utilizar la técnica para agregar un parámetro implícito ficticio para hacer que la firma sea diferente:

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


Supongo que le gustaría que las llamadas al método sean más bonitas y, por lo tanto, las llamadas explícitas con _* no son una opción. En ese caso, puede resolver el problema con la sobrecarga de métodos.

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()) }


Un método que toma varargs también está tomando una secuencia, por lo que no es necesario definir un constructor auxiliar o un método sobrecargado.

Dado

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

puedes llamarlo asi

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

o

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

Además, en su pregunta, está llamando al método seq en el parámetro params. Esto probablemente no hace lo que pretendías. seq se utiliza para garantizar que las operaciones en la colección resultante se ejecuten de forma secuencial en lugar de en paralelo. El método se introdujo con las colecciones paralelas en la versión 2.9.0 de Scala.

Lo que probablemente quiso usar fue toSeq, que devuelve la colección en la que se usó y se convirtió a Seq (o si ya es una Seq). Pero como los parámetros de varargs ya están escritos como Seq, de todos modos es un no-op.