如何在Scala中创建带有有界类型参数的自定义Seq?
考虑以下工作自定义Seq:
class MySeq[B](val s: Seq[B]) extends Seq[B] with GenericTraversableTemplate[B,MySeq] with SeqLike[B,MySeq[B]] { override def companion = MySeq def iterator = s.iterator def apply(i: Int) = s(i) def length = s.length override def toString = s map { _.toString } mkString("n") } object MySeq extends SeqFactory[MySeq] { implicit def canBuildFrom[B]: CanBuildFrom[Coll,B,MySeq[B]] = new GenericCanBuildFrom[B] def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq)) } 我想对类型参数B施加一个限制.换句话说,我想要这样的东西(不工作): class MyA class MySeq[+B <: MyA](val s: Seq[B]) extends Seq[B] with GenericTraversableTemplate[B,MySeq[B]] { override def companion = MySeq // Type Mismatch Here def iterator = s.iterator def apply(i: Int) = s(i) def length = s.length override def toString = s map { _.toString } mkString("n") } object MySeq extends SeqFactory[MySeq] { implicit def canBuildFrom[B]: CanBuildFrom[Coll,MySeq[B]] = new GenericCanBuildFrom[B] // Type Mismatch in the line below def newBuilder[B] = new ListBuffer[B] mapResult (x => new MySeq(x.toSeq)) } 但是我在指定的行中出现以下类型不匹配错误: inferred type arguments [B] do not conform to class MySeq's type parameter bounds [+B <: MyA] Main.scala line 49 type mismatch; found : countvotes.structures.MySeq.type required: scala.collection.generic.GenericCompanion[Seq] Main.scala line 36 type mismatch; found : MySeq[B(in class MySeq)] required: MySeq[B(in method newBuilder)] Main.scala line 49 type mismatch; found : scala.collection.immutable.Seq[B(in method newBuilder)] required: Seq[B(in class MySeq)] Main.scala line 49 我试图通过向CanBuildFrom和newBuilder的类型参数添加边界来解决这个问题,但后来我得到了其他错误消息. 如何创建绑定了类型参数的自定义Seq? 解决方法
我没有收到第26行的错误:
override def companion = MySeq 也许还有其他因素导致了这一点 无论如何,问题是你不能拥有GenericCompanion [MySeq](SeqFactory的超类型).原因是GenericCompanion [Coll]意味着你可以为任何A构造一个Coll [A](参见newBuilder的签名).你也不能拥有MySeq [A]<:GenericTraversableTemplate [A,MySeq],因为genericBuilder是不可能的.这是有道理的; MySeq实际上不是一个“通用集合”,因为它希望它的元素都是MyA. 解决方案是让MySeq [B]<:GenericTraversableTemplate [B,Seq],(免费扩展Seq).然后你有两个伴侣选择.它可以是Seq的默认值,也可以是s.companion.在第一种情况下,((as:MySeq [A]):Seq [A]).map(...)将产生一个List(在运行时;在编译时它只是一个通用的Seq).在第二个中,它将取决于as.s是什么(再次,在运行时;编译时只会看到一个Seq).但是,你可以保留扩展的SetLike. 然后,您需要提供自定义CanBuildFrom:MySeq.canBuildFrom [A< ;: MyA]:CanBuildFrom [MySeq [A],A,MySeq [A]],并定义MySeq#newBuilder. class MySeq[+B <: MyA](val s: Seq[B]) extends Seq[B] with SeqLike[B,MySeq[B]] { override def iterator = s.iterator override def apply(i: Int) = s(i) override def length = s.length override def toString = s.map(_.toString).mkString("n") override def companion = s.companion protected[this] override def newBuilder: mutable.Builder[B,MySeq[B]] = new mutable.Builder[B,MySeq[B]] { private[this] val base = s.genericBuilder[B] override def +=(elem: B) = { base += elem; this } override def clear() = base.clear() override def result() = new MySeq[B](base.result()) } } object MySeq { implicit def canBuildFrom[A <: MyA]: CanBuildFrom[MySeq[_],MySeq[A]] = ??? } val list = List(new MyA,new MyA,new MyA) val vect = list.toVector val mLst = new MySeq(list) val mVec = new MySeq(vect) { val res = mLst.filter(_.hashCode != list.head.hashCode) implicitly[res.type <:< MySeq[MyA]] } { val res = (mVec: Seq[MyA]).map(identity) assert(res.isInstanceOf[Vector[_]]) } { val res = (mLst: Seq[MyA]).map(identity) assert(res.isInstanceOf[List[_]]) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |