假设我正在编写应该易于扩展且无需详细语法即可使用的库代码。看起来像隐式转换可以用来避免冗长,就像在Scala Collections库中一样,但我正在努力将它应用于遍历,如下所示。
我有一个特点:
trait Wrapped[T]
{
def value : T
}
然后我有了类Foo
,它是库中的一个关键类。 Foo
是使用Wrapped
。
case class Foo[T <: Wrapped[_]](lst : Traversable[T]) {
override def toString = lst mkString " "
}
一个常见的用例是包裹Int
所以我提供了WrappedInt
类:
case class WrappedInt(value : Int) extends Wrapped[Int]
使用此代码,我可以像这样Foo
:
val wrappedInts = Seq(1, 2, 3, 4) map { new WrappedInt(_) }
val someFoo = Foo(wrappedInts)
我不喜欢在这里包装的额外代码。我希望以下代码是等效的:
val foo = Foo(Seq(1, 2, 3, 4)) //should be a Foo[WrappedInt] - gives error
我定义了以下内容:
object Conversions {
implicit def intsToWrapped(lst : Traversable[Int]) = lst map { new WrappedInt(_) }
}
但是,它仍然不起作用,我的val foo
在将Foo
构造函数参数更改为implicit lst
后出现编译错误。 Scala书中说隐式转换基本上允许x + y
更改为convert(x) + y
,其中convert
是隐式转换。在我看来,我有相同的确切情况,这里一个参数的一次转换就足够了。我通过这样做验证:
val foo = Foo(Conversions.intsToWrapped(Seq(1, 2, 3, 4)))
为什么我的隐含未被应用?在当前的Scala中是否有一种不同的,更惯用的方式来让Foo
用更少的代码构建?
编辑:添加import Conversions._
没有帮助,如果我理解正确,则没有必要,因为此示例位于一个文件中。
我得到的具体编译器错误是:
val foo = Foo(Seq(1, 2, 3, 4))
inferred type arguments [Int] do not conform to method apply's type parameter bounds [T <: Wrapped[_]]
type mismatch; found : Seq[Int] required: Traversable[T]
指定帮助类型推断的类型,如下所示:
val foo = Foo[WrappedInt](Seq(1, 2, 3, 4))
为每个int提供一条消息,如
type mismatch; found : Int(1) required: WrappedInt
答案 0 :(得分:2)
您可以在foo的构造函数中指定隐式转换(曾经是视图边界)。您必须指定集合元素是&#34;可查看的&#34;作为他们的包装版本,而不是集合本身。
trait Wrapped[T] {
def value : T
}
// you can specify bounds on W if you want to be able to do something specific on the values, e.g. W <: MyClass
case class Foo[T, W](lst : Traversable[T])(implicit asWrapped: T => Wrapped[W]) {
override def toString = lst.map(_.value) mkString " "
}
case class WrappedInt(value : Int) extends Wrapped[Int]
// This is your implicit conversion from Int to WrappedInt
implicit def intToWrapped(x : Int): WrappedInt = WrappedInt(x)
val wrappedInts = Seq(1, 2, 3, 4) map { new WrappedInt(_) }
val someFoo = Foo(wrappedInts)
val foo = Foo(Traversable(1, 2, 3, 4))