scala - 案例类作为集合的 "wrapper"类。 map/foldLeft/怎么样

标签 scala

我试图做的是想出一个案例 我可以在模式匹配中使用的类,它只有一个字段,例如一个不可变的集合。此外,我想使用 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 不同的类型
  • 类型必须是案例类(我们要做模式匹配)
  • 我们需要“委托(delegate)”方法 map、foldLeft 等,它们应该将调用传递给我们的实际集合,并以我们的新类型
  • 返回结果集包裹的 arround

    我的第一个想法是扩展 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 ),但对于其他方法,例如 mapflatMap您需要提供适当的 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/

    相关文章:

    scala - 如何在sbt多项目构建中获取子项目路径

    scala - 在 Scala 中表示值约束的最佳方法?

    scala - 创建Kafka流的AbstractMethodError

    scala - 如果使用注入(inject),则 PlaySpec 测试类未被拾取

    java - 如何解决scala代码中超出GC过载限制的问题

    scala - 在reactivemongo中找不到BSON Writer的隐式值

    java - Akka 远程处理 : Dead Letters after enabling Serialization

    scala - 在 Scala 中使用 Recovery 组合 Futures

    scala - 将 S3 挂载到数据 block

    list - 如何替换列表中的给定项目?