Scala: Constructor taking either Seq or varargs

社会主义新天地 提交于 2019-11-30 11:05:37

A method taking varargs is also always taking a sequence, so there is no need to define an auxiliary constructor or overloaded method.

Given

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

you can call it like this

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

or

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

Also, in your question, you are calling method seq on the params parameter. This probably does not do what you intended. seq is used to ensure that operations on the resulting collection are executed sequentially instead of in parallel. The method was introduced with the parallel collections in version 2.9.0 of Scala.

What you probably wanted to use was toSeq, which returns the collection it is used on converted to a Seq (or itself if it is already a Seq). But as varargs parameters are already typed as Seq, that is a no-op anyway.

No: actually, Any* is actually almost identical to Seq[Any], not to Array[Any].

To disambiguate between the two, you can use the technique to add a dummy implicit parameter to make the signature different:

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

I suppose that you would like to make the method calls prettier and so explicit calling with _* is not an option. In that case you may solve the problem with method overloading.

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())
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!