【问题标题】:Create custom Seq collection in Scala在 Scala 中创建自定义 Seq 集合
【发布时间】:2017-05-17 00:44:43
【问题描述】:

我想从现有的 Seq 集合创建一个新的自定义 Scala 集合。我有一个名为Ref 的特征,其中包含如下数据

trait Ref[A] {
   def get: A
   def getAsOption: Option[A]
   def dataType: Class[A]
   // other methods
}

我的自定义集合名为Vec,它是Ref[A]Sequence(即Vec[A] 等效于Seq[Ref[A]]),我想创建这样的自定义集合的原因是我想保留该类型集合中Ref 的参数以在自定义方法中处理。我的代码如下

trait VecLike[A, +Repr <: Seq[Ref[A]]]
  extends SeqLike[Ref[A], Repr]
  with TraversableLike[Ref[A], Repr] {
// custom methods
}

trait GenVec[A]
  extends VecLike[A, Seq[Ref[A]]]
  with Seq[Ref[A]]
  with PartialFunction[Int, Ref[A]]

abstract class AbstractVec[A](vec: Ref[A]*)
  extends AbstractSeq[Ref[A]]
  with GenVec[A] {...}

class Vec(vec: Ref[A]*)
  extends AbstractVec[A](vec:_*)
  with VecLike[A, Vec[A]]
  with GenericTraversableTemplate[Ref[A], Seq]

但是当我调用map()函数时

Vec(1,2,3,4).map(intToString) 

它返回一个Seq[String],预期的结果是Vec[String]。我还尝试使用SeqFactory[Seq] 在伴随对象中创建自定义CanBuildFrom,但它失败了。 :( :(

谁能给我一些关于这方面的建议以及我如何实现这一目标?

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    你需要实现一个自定义的Builder 并让VecLike 中的newBuilder 方法返回它。 查看此页面以获取有关实现自定义集合的非常好的教程:http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html

    【讨论】:

    • 我本来想感谢这篇评论的作者,然后意识到它来自@Dima。什么巧合?哦,这是这个问题的最佳答案。
    【解决方案2】:

    我完成了,这是我的错误,我创建了错误的 CanBuildFrom。下面是 CanBuildFrom 的完整实现(CBF Inspired from Scala GenericCanBuildFrom)

    trait VecLike[A, +Repr]
      extends SeqLike[Ref[A], Repr]
    
    trait GenVec[A]
      extends AnyRef
      with VecLike[A, GenVec[A]]
    
    trait Vec[A]
      extends GenVec[A]
      with VecLike[A, Vec[A]]
    
    abstract class AbstractVec[A](vec: Seq[Ref[A]])
      extends AnyRef
      with Vec[A]
    
    final class VecImpl[A](vec: Seq[Ref[A]])
      extends AbstractVec[A](vec)
    
    object Vec {
    
    
      private[this] val VecCBFInstance: VecCanBuildFrom[Nothing] = new VecCanBuildFrom[Nothing] {
        override def apply() = newBuilder[Nothing]
      }
      private def VecCBF: VecCanBuildFrom[Nothing] = VecCBFInstance
      private class VecCanBuildFrom[A] extends CanBuildFrom[Vec[_], A, Vec[A]] {
        def apply(from: Vec[_]) = newBuilder[A]
        def apply() = newBuilder[A]
      }
      implicit def canBuildFrom[A]: CanBuildFrom[Vec[_], A, Vec[A]] = VecCBF.asInstanceOf[VecCanBuildFrom[A]]
    
    }
    

    现在我可以在调用 map() 函数后接收 Vec 结果而不是 Seq,如下所示

    val vec = Vec(1,2,3,4)
    var vecStr : Vec[String] = vec.map(intToString)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 2018-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多