为SeqLike创建扩展方法

时间:2013-12-06 14:32:20

标签: scala collections implicit-conversion

假设我想扩展SeqLike的功能:

import collection.SeqLike

implicit class Test[A, Repr <: SeqLike[A, Repr]](val sq: Repr) extends AnyVal {
  def foo(): Repr = sq
}

然后这不起作用:

Vector(1, 2, 3).foo()

也不是:

new Test(Vector(1, 2, 3)).foo()

<console>:41: error: inferred type arguments
                    [Nothing,scala.collection.immutable.Vector[Int]] 
                    do not conform to class Test's type parameter bounds 
                    [A,Repr <: scala.collection.SeqLike[A,Repr]]
              new Test(Vector(1, 2, 3)).foo()
              ^

只有这样才有效:

new Test[Int, Vector[Int]](Vector(1, 2, 3)).foo()

如何让隐式类工作?

2 个答案:

答案 0 :(得分:2)

只需输入sq作为SeqLike而不是类型参数。这将允许编译器有一些可依赖的坚实基础,然后可以推断Repr。 现在唯一明显的问题是我们在foo中会出现类型不匹配,因为它应该返回Repr但我们会返回SeqLike[A, Repr]

解决方案很简单,使用repr方法:

implicit class Test[A, Repr](val sq: SeqLike[A, Repr]) extends AnyVal {
  def foo(): Repr = sq.repr
}
Vector(1, 2, 3).foo()

答案 1 :(得分:1)

我通常会这样解决这个问题:

implicit class Test[A, Repr <: SeqLike[A, Repr]](val sq: Repr with SeqLike[A, Repr]) extends AnyVal {

但是,这对ArrayString无效,因此IsTraversableLike是更好的解决方案。如果您确实需要SeqLike,则很容易复制IsTraversableLike