7

我有库方法采用变量参数列表并生成数据

class Data
def process(elems: String*): Data = new Data

我希望我的字符串被隐式转换为Data

implicit def strToData(ts: String): Data = process(t)

所以我可以写类似

val data: Data = "one"

但我也希望隐式转换字符串元组。我添加了另一个隐式

implicit def strsToData(ts: String*): Data = process(ts: _*)

它编译得很好,但转换失败

val data: Data = ("one", "two")
val dat3: Data = ("one", "two", "three")
val dat4: Data = ("one", "two", "three", "four")

found   : Seq[java.lang.String]
required: this.Data
val data: Data = Seq("one", "two")

有什么方法可以隐式转换元组,或者可以实现它的原因吗?

更新:元组可以是任何数量。

4

3 回答 3

5
  1. ts: String*不是一个元组,而是一个Iterable. 您不能将 iterable 转换为 tuple,因为 tuple 是一种静态类型,并且它的 arity 是在编译时解析的。Emil H 回答了如何从元组进行隐式转换。
  2. 从一种类型到另一种类型的透明隐式转换是一个常见的陷阱,我们不鼓励这样做。相反,您应该应用“包装器”方法,或从 Scala 2.10 开始使用“值类”:

    在 Scala 2.9 中:

    implicit def stringStringTupleExtender (ts : (String, String)) =
      new {
        def data = process(ts)
      }
    

    在 Scala 2.10 中:

    implicit class StringStringTupleExtender (val ts : (String, String)) extends AnyVal {
      def data = process(ts)
    }
    

    然后你会像这样使用它:

    val data : Data = ("sdf", "lsdfj").data
    val data1 : Data = "sdf".data // if you do the same for String
    
  3. 如果您正在寻找动态解析任何输入集合,那么猜猜看,您应该使用集合,而不是元组。

    在 Scala 2.9 中

    implicit def seqExtender (ts : Seq[String]) =
      new {
        def data = process(ts)
      }
    

    用法:

    val data : Data = Seq("sdf", "lsdkfjsdl", "ldsfjk").data
    
于 2012-07-27T11:14:53.280 回答
3

虽然@NikitaVolkov 的答案中的所有警告都适用于双重力量,但您可以编写一个接受任何元组数量以及任何案例类的版本:

implicit def prod2data(Product p): process((p.productIterator.toSeq):_*)
于 2012-07-27T15:11:27.827 回答
2

您需要创建从元组到的隐式转换Data

implicit def strTplToData(ts:(String, String)) = process(ts._1, ts._2)

然后你可以这样做:

val data: Data = ("one", "two")
于 2012-07-27T10:48:01.230 回答