Scala:构造函数采用Seq或varargs

wen*_*wen 20 constructor types scala variadic-functions

我猜测,出于兼容性原因,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)
}
Run Code Online (Sandbox Code Playgroud)

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

double definition:构造函数Api:(api_url:String,params:(String,String)*)Api和构造函数Api:(api_url:String,params:Seq [(String,String)])第13行的Api在擦除后具有相同的类型:(api_url:java.lang.String,params:Seq)Api

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

Rue*_*ler 32

采用varargs的方法也总是采用序列,因此不需要定义辅助构造函数或重载方法.

特定

class Api(api_url: String, params: (String, String)*)
Run Code Online (Sandbox Code Playgroud)

你可以这样称呼它

new Api("url", ("a", "b"), ("c", "d"))
Run Code Online (Sandbox Code Playgroud)

要么

val seq = Seq(("a", "b"), ("c", "d"))
new Api("url", seq:_*)
Run Code Online (Sandbox Code Playgroud)

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

你可能想要使用的是toSeq,它返回它在转换为Seq时使用的集合(如果它已经是Seq,则返回它本身).但是由于varargs参数已经被输入为Seq,所以无论如何都是无操作.

  • 我可以指出类型注释`:_*`是使用与varargs构造函数兼容的sequence参数真正使构造函数调用的原因.更多细节:http://stackoverflow.com/questions/6051302/what-does-colon-underscore-star-do-in-scala (6认同)

Jea*_*let 10

不:实际上,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)
}
Run Code Online (Sandbox Code Playgroud)

  • 好吧,随意提供一个不那么"恶心"的解决方案! (5认同)
  • 为什么不保留varargs构造函数并让调用者执行`seq:_*`如果他想要的话? (4认同)