3

假设我有一个名为 LongArrayWritable 的类型,它是 Long 数组的盒装表示。我有在这些类型之间转换的隐式定义:

implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}

现在,我也有隐式在 java.lang.Iterable 和 scala.collection.List[X] 之间转换的通用形式:

implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }

有了这些定义,scala 编译器可以推断出 java.lang.Iterable[LongArrayWritable] 和 List[Array[Long]] 之间的隐式转换(相当于iterator2list(iterator).map(unboxLongArray(_))),或者这超出了implicits 的能力,因此需要它自己的(显式?)隐式定义?

谢谢,

蒂姆

4

1 回答 1

7

有一篇文章涵盖了这个问题:如何在 Scala 中链接隐式?. 本质上,您需要有一个视图绑定到LongArrayWritable. 这意味着,def转换为LongArrayWritable的隐式接收一个隐式参数(称为视图绑定),因此 this 的参数def不是直接的,Array而是可以转换为的某种类型Array

object LongArrayWritable {
  implicit def fromArraySource[A <% Array[Long]](a: A): LongArrayWritable = apply(a)
}
case class LongArrayWritable(a: Array[Long])

def test(a: LongArrayWritable): Unit = println("OK")

现在这适用于数组:

test(Array( 1L, 2L, 3L))

但是,由于Arrayis not anIterable并且在范围内没有从Iterableto的默认转换Array,您需要添加一个:

implicit def iterable2Array[A: ClassManifest](i: Iterable[A]): Array[A] = i.toArray

然后它工作:

test(List(1L, 2L, 3L))

视图绑定A <% Array[Long]是 type 隐式参数的快捷方式A => Array[Long],因此您也可以编写

implicit def fromArraySource[A](a: A)(implicit view: A => Array[Long]) ...
于 2011-03-30T13:48:52.373 回答