我试图做的是想出一个案例 我可以在模式匹配中使用的类,它只有一个字段,例如一个不可变的集合。此外,我想使用 map、foldLeft 等应该传递给集合的函数。我尝试如下:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
现在,如果我尝试使用例如map 函数,我得到一个类型错误:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
类型错误非常好(在我的理解中)。但是,我想知道如何为一个集合实现一个包装案例类,以便可以调用 map、foldLeft 等并仍然接收案例类的对象。需要覆盖所有这些功能还是有其他方法?
编辑
我倾向于接受对我有用的 Régis Jean-Gilles 的解决方案。然而,在谷歌上搜索了几个小时后,我发现了另一个有趣的 Scala 特征,名为
SetProxy
。 .我找不到任何琐碎的例子,所以我不确定这个特征是否符合我的要求:Set
不同的类型我的第一个想法是扩展
Set
但我的自定义类型 Foo
已经扩展了另一个类。因此,第二个想法是混合特征 Iterable 和 IterableLike。现在我对这个特征感到兴奋SetProxy
这让我想到哪个是“最好的”方式。你有什么想法和经历?自从我三天前开始学习 Scala 以来,任何指针都非常感谢!
最佳答案
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
你说的对。仅继承自
IterableLike
如 mpartel 所示,返回类型为 一些更精确的方法(例如 filter
,它将返回 Foo
),但对于其他方法,例如 map
的 flatMap
您需要提供适当的 CanBuildFrom
隐含的。这是一个执行此操作的代码片段:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
在 repl 中进行了一些测试:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
关于scala - 案例类作为集合的 "wrapper"类。 map/foldLeft/怎么样,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16505314/