Scala的含义是否可以转换为更高级别的类型?

mis*_*tim 3 generics types scala implicits

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

implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}
Run Code Online (Sandbox Code Playgroud)

现在,我也有一些暗示,它们以通用形式在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 */ }
Run Code Online (Sandbox Code Playgroud)

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

谢谢,

蒂姆

0__*_*0__ 7

有一篇帖子涵盖了这个问题:如何在Scala中链接implicits?.从本质上讲,您需要有一个视图绑定转换为LongArrayWritable.这意味着,隐式def转换为LongArrayWritable接收一个隐式参数(称为视图绑定),因此这个参数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")
Run Code Online (Sandbox Code Playgroud)

现在这适用于数组:

test(Array( 1L, 2L, 3L))
Run Code Online (Sandbox Code Playgroud)

然而,由于Array不是Iterable,也没有默认的转换,从IterableArray的范围,你需要添加一个:

implicit def iterable2Array[A: ClassManifest](i: Iterable[A]): Array[A] = i.toArray
Run Code Online (Sandbox Code Playgroud)

然后它工作:

test(List(1L, 2L, 3L))
Run Code Online (Sandbox Code Playgroud)

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

implicit def fromArraySource[A](a: A)(implicit view: A => Array[Long]) ...
Run Code Online (Sandbox Code Playgroud)