如何创建具有特定类型的List的包装 [英] How to create a wrapper of List with a specific type

查看:273
本文介绍了如何创建具有特定类型的List的包装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建具有特定类型(例如List[Int])的List包装器,以便采用隐式CanBuildFrom参数的方法返回我的包装器实例,而不是List.

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])

是否有更好/更简便的方法来创建这样的包装器,或者我错过了实现MyList的任何重要事项?

Is there a better/easier way to create such a wrapper or did I miss anything important in the implementation of MyList?

:一个后续问题是:是否可以将整个包装器逻辑放入ListWrapper类或特征中,以便可以像这样实现上述MyList:

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]

推荐答案

据我阅读本文了解的范围:

As far I know from reading this article:

http://www.scala-lang .org/docu/files/collections-api/collections-impl.html

如果需要filter/map/etc,您的解决方案是最简单的解决方案.返回所有MyList实例.像filter这样的操作需要newBuilder,而像map这样的操作需要隐式CanBuildFrom,这可能会更改集合类型.

your solution is the simplest one, if you want filter/map/etc. to all return instances of MyList. newBuilder is needed for ops like filter, and the implicit CanBuildFrom for ops like map, which may change the collection type.

您可能在CanBuildFrom中应该做的是这样:

What you should maybe do in your CanBuildFrom is this:

def apply(from: MyList) = from.newBuilder // call it on `from'

可以确保静态类型MyList上的map实际上具有动态类型,而该动态类型是MyList的子类型,

which ensures that a map on a statically-typed MyList which actually has a dynamic type that is a subtype of MyList will reuse that same dynamic type.

编辑:似乎缺少一些内容,为此map返回的是List而不是MyList的实例:

Edit: seems like there is a little something missing, for this map returns an instance of List and not MyList:

val l1: LinearSeq[Int] = new MyList(List(1, 2, 3))
println(l1.map(_ + 1)) // prints List(2, 3, 4)

从链接的文章中获取RNA示例的情况也是如此.如果它具有静态类型IndexedSeq[Base]而不是RNA,则其上的map返回向量.

it looks like this is also the case with the RNA example taken from the linked article. If it has static type IndexedSeq[Base] instead of RNA, a map on it returns a vector.

编辑2 :看来这是一个更普遍的问题,在此问题中进行了讨论.

Edit 2: looks like this is a more general problem, discussed in this question.

这篇关于如何创建具有特定类型的List的包装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆