说我有以下数据结构:
case class Timestamped[CC[M] < Seq[M]](elems : CC, timestamp : String)
所以它本质上是一个带有属性的序列 - 一个时间戳 - 附加到它上面。这很好用,我可以使用语法
创建新实例val t = Timestamped(Seq(1,2,3,4),"2014-02-25")
t.elems.head // 1
t.timestamp // "2014-05-25"
语法很笨拙,而我希望能够做到这样的事情:
Timestamped(1,2,3,4)("2014-02-25")
t.head // 1
t.timestamp // "2014-05-25"
时间戳只是Seq
及其实施SeqLike
的扩展,只有一个属性val timestamp : String
。
这似乎很容易;只需使用带有mixin Seq
的{{1}}即可。但我无法弄清楚如何创建构造函数。 我的问题是:如何在随播对象中创建一个构造函数,创建一个带有额外成员值的序列?签名如下:
TimestampMixin { val timestamp : String }
你会发现它不是直截了当的;集合使用object Timestamped {
def apply(elems: M*)(timestamp : String) : Seq[M] with TimestampMixin = ???
}
来实例化自己,所以我不能简单地调用构造函数覆盖一些Builder
s。
答案 0 :(得分:2)
Scala集合是一个非常复杂的结构。扩展Seq
需要实施apply
,length
和iterator
方法。最后,您可能最终会复制List
,Set
或其他内容的现有代码。你也可能不得不为你的收藏担心CanBuildFrom
,如果你只是想添加一个字段,我认为这不值得。
相反,请考虑从Timestamped
类型到Seq
的隐式转换。
case class Timestamped[A](elems: Seq[A])(timestamp: String)
object Timestamped {
implicit def toSeq[A](ts: Timestamped[A]): Seq[A] = ts.elems
}
现在,每当我尝试从Seq
调用方法时,编译器都会隐式地将Timestamped
转换为Seq
,我们可以正常进行。
scala> val ts = Timestamped(List(1,2,3,4))("1/2/34")
ts: Timestamped[Int] = Timestamped(List(1, 2, 3, 4))
scala> ts.filter(_ > 2)
res18: Seq[Int] = List(3, 4)
这里有一个主要的缺点,就是在对原始Seq
执行操作后,我们现在仍然遇到Timestamped
。
答案 1 :(得分:0)
走另一条路...延伸Seq,它只有3个抽象成员:
case class Stamped[T](elems: Seq[T], stamp: Long) extends Seq[T] {
override def apply(i: Int) = elems.apply(i)
override def iterator = elems.iterator
override def length = elems.length
}
val x = Stamped(List(10,20,30), 15L)
println(x.head) // 10
println(x.timeStamp) // 15
println(x.map { _ * 10}) // List(100, 200, 300)
println(x.filter { _ > 20}) // List(30)
请记住,只有Seq对您的用例足够具体,这才有效,如果您以后发现需要更复杂的收集行为,这可能会变得站不住脚。
编辑:添加了一个更接近您尝试创建的签名的版本。不确定这是否对您有所帮助:
case class Stamped[T](elems: T*)(stamp: Long) extends Seq[T] {
def timeStamp = stamp
override def apply(i: Int) = elems.apply(i)
override def iterator = elems.iterator
override def length = elems.length
}
val x = Stamped(10,20,30)(15L)
println(x.head) // 10
println(x.timeStamp) // 15
println(x.map { _ * 10}) // List(100, 200, 300)
println(x.filter { _ > 20}) // List(30)
elems最终将成为一般创建的WrappedArray
。