如何创建具有特定类型的 List 的包装器
我正在尝试创建具有特定类型(例如 List[Int]
)的 List
包装器,以便采用隐式 CanBuildFrom
参数的方法返回我的包装器的实例而不是 List
。
一种可能的解决方案(感觉相当重量级)是:
import scala.collection._
import generic.{CanBuildFrom, SeqForwarder}
import mutable.{Builder, ListBuffer}
class MyList(list: List[Int]) extends immutable.LinearSeq[Int]
with LinearSeqLike[Int, MyList]
with SeqForwarder[Int] {
override def newBuilder: Builder[Int, MyList] = MyList.newBuilder
protected override def underlying = list
}
object MyList {
def newBuilder: Builder[Int, MyList] =
new ListBuffer[Int] mapResult(new MyList(_))
implicit def canBuildFrom: CanBuildFrom[MyList, Int, MyList] = {
new CanBuildFrom[MyList, Int, MyList] {
def apply(from: MyList) = from.newBuilder
def apply() = newBuilder
}
}
}
val l1 = new MyList(List(1,2,3))
println(l1.isInstanceOf[MyList])
println(l1.map(_ + 1).isInstanceOf[MyList])
println(l1.filter(_ == 2).isInstanceOf[MyList])
是否有更好/更简单的方法来创建这样的包装器,或者我是否错过了 MyList 实现中的任何重要内容?
编辑:后续问题是:是否可以将整个包装器逻辑放入 ListWrapper
类或特征中,以便可以实现上述 MyList
像这样:
class MyList extends ListWrapper[Int, MyList]
object MyList extends ListWrapperFactory[Int, MyList]
I am trying to create a wrapper of List
with a specific type (e.g. List[Int]
) such that methods that take an implicit CanBuildFrom
parameter return an instance of my wrapper instead of List
.
One possible solution, which feels rather heavyweight, is:
import scala.collection._
import generic.{CanBuildFrom, SeqForwarder}
import mutable.{Builder, ListBuffer}
class MyList(list: List[Int]) extends immutable.LinearSeq[Int]
with LinearSeqLike[Int, MyList]
with SeqForwarder[Int] {
override def newBuilder: Builder[Int, MyList] = MyList.newBuilder
protected override def underlying = list
}
object MyList {
def newBuilder: Builder[Int, MyList] =
new ListBuffer[Int] mapResult(new MyList(_))
implicit def canBuildFrom: CanBuildFrom[MyList, Int, MyList] = {
new CanBuildFrom[MyList, Int, MyList] {
def apply(from: MyList) = from.newBuilder
def apply() = newBuilder
}
}
}
val l1 = new MyList(List(1,2,3))
println(l1.isInstanceOf[MyList])
println(l1.map(_ + 1).isInstanceOf[MyList])
println(l1.filter(_ == 2).isInstanceOf[MyList])
Is there a better/easier way to create such a wrapper or did I miss anything important in the implementation of MyList
?
Edit: A follow-up question is: Can this whole wrapper logic be put into ListWrapper
classes or traits so that the above MyList
can be implemented like this:
class MyList extends ListWrapper[Int, MyList]
object MyList extends ListWrapperFactory[Int, MyList]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
据我阅读这篇文章所知:
http:// /www.scala-lang.org/docu/files/collections-api/collections-impl.html
如果您想要过滤器/地图/等,您的解决方案是最简单的。到
MyList
的所有返回实例。filter
等操作需要newBuilder
,而map
等操作需要隐式CanBuildFrom
,这可能会更改集合类型。您在
CanBuildFrom
中应该做的是:确保静态类型
MyList
上的map
实际上具有动态类型是MyList
的子类型将重用相同的动态类型。编辑:似乎缺少一些东西,因为此
map
返回List
的实例,而不是MyList
:看起来链接文章中的
RNA
示例也是如此。如果它具有静态类型IndexedSeq[Base]
而不是RNA
,则其上的map
返回一个向量。编辑2:看起来这是一个更普遍的问题,在这个问题中讨论。
As far I know from reading this article:
http://www.scala-lang.org/docu/files/collections-api/collections-impl.html
your solution is the simplest one, if you want filter/map/etc. to all return instances of
MyList
.newBuilder
is needed for ops likefilter
, and the implicitCanBuildFrom
for ops likemap
, which may change the collection type.What you should maybe do in your
CanBuildFrom
is this:which ensures that a
map
on a statically-typedMyList
which actually has a dynamic type that is a subtype ofMyList
will reuse that same dynamic type.Edit: seems like there is a little something missing, for this
map
returns an instance ofList
and notMyList
:it looks like this is also the case with the
RNA
example taken from the linked article. If it has static typeIndexedSeq[Base]
instead ofRNA
, amap
on it returns a vector.Edit 2: looks like this is a more general problem, discussed in this question.
关于我的后续问题如何通过类或特征混合包装器逻辑,这就是我想到的:
现在
MyList
可以通过以下方式实现:这绝对比将所有样板代码放在其中要好
MyList
的定义,但是要使MyList
成为List
的包装器,仍然需要编写很多代码。Regarding my follow-up question how to mixin the wrapper logic via classes or traits, this is what I came up with:
Now
MyList
can be implemented by:This is definitely better than having all the boilerplate code in
MyList
's definition, but it is still a lot to write for makingMyList
just a wrapper forList
.