Scala:构造函数采用 Seq 或 varargs

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7040382/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:20:33  来源:igfitidea点击:

Scala: Constructor taking either Seq or varargs

scalatypesconstructorvariadic-functions

提问by wen

I am guessing that, for compatibility reasons, the type of vararg parameters Any*is Array[Any] - please correct this if I'm wrong. However, this does not explain the following error:

我猜测,出于兼容性原因,可变参数的类型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)
}

This code does not compile, but gives the warning:

此代码不会编译,但会发出警告:

double definition: constructor Api:(api_url: String, params: (String, String)*)Api and constructor Api:(api_url: String, params: Seq[(String, String)])Api at line 13 have same type after erasure: (api_url: java.lang.String, params: Seq)Api

双重定义:构造函数 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

So how do I define a constructor taking either varargs or a sequence?

那么我如何定义一个采用可变参数或序列的构造函数呢?

回答by Ruediger Keller

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

采用 varargs 的方法也始终采用序列,因此无需定义辅助构造函数或重载方法。

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.

此外,在您的问题中,您正在对 params 参数调用方法 seq。这可能不符合您的意图。seq 用于确保对结果集合的操作按顺序执行,而不是并行执行。该方法是在 Scala 2.9.0 版的并行集合中引入的。

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.

您可能想要使用的是 toSeq,它返回它用于转换为 Seq 的集合(如果它已经是 Seq,则返回它本身)。但是由于 varargs 参数已经被输入为 Seq,这无论如何都是一个空操作。

回答by Jean-Philippe Pellet

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

不:实际上,Any*实际上几乎等同于Seq[Any],而不是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)
}

回答by ayvango

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.

我想你想让方法调用更漂亮,所以显式调用 with_*不是一种选择。在这种情况下,您可以通过方法重载来解决问题。

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