【发布时间】:2011-03-03 17:44:38
【问题描述】:
假设你想为所有的 Iterables 添加一些方法。可能是这样的:
import collection.generic.CanBuildFrom
class Foo[P, S[X] <: Iterable[X]](val s : S[P]) {
def bar(j : P)(implicit bf : CanBuildFrom[S[P],P,S[P]]) : S[P] = {
val builder = bf(s)
builder ++= s
builder += j
builder.result
}
def oneBar(j : P)(implicit bf : CanBuildFrom[S[P],P,S[P]]) : P = bar(j).head
}
implicit def iter2foo[P, S[X] <: Iterable[X]](s : S[P]) = new Foo[P,S](s)
现在,像这样的代码
println(Seq(1,2,3,4) bar 5)
编译和执行顺利。不过,
println((1 to 4) bar 5)
原因
error: value bar is not a member of scala.collection.immutable.Range.Inclusive
with scala.collection.immutable.Range.ByOne
我认为这可能是因为隐式转换要求 (?) 参数的类型具有类型参数(Range 没有)。但是
implicit def iter2foo[P, S <: Iterable[P]](s : S) = new Foo[P,Iterable](s)
不会改变任何东西。请注意,Range 扩展了 Iterable[Int]。
我做错了什么?如何编写一个适用于 Iterable 的所有子类型的隐式转换,无论是否通用?
编辑:我只是注意到更简单
implicit def iter2foo[P](s : Iterable[P]) = new Foo[P,Iterable](s)
按预期工作(在 REPL 上)。或者是吗?这种解决方案有缺点吗?
编辑 2: 缺点是bar 的静态结果类型只会是Iterable[P],而不是更具体的类型。但是,构造的集合具有正确的(实际)类型。
【问题讨论】:
标签: generics scala implicit-conversion