《Programming in Scala 3rd》阅读笔记

Chapter 25《The Architecture of S

2018-08-13  本文已影响0人  liqing151

不同的集合支持实现支持相同的操作,如果在每个集合里面进行单独的实现,会出现大量的代码并且不利于保持集合操作的一致性。新的集合框架主要设计目标就是避免重复,在尽量少的地方定义,并在集合模板中实现大多数操作,由基类和实现灵活继承。


集合构建器

class Builder[-Elem, +To] {
def +=(elem: Elem): this.type
def result(): To
def clear()
def mapResult[NewTo](f: To => NewTo): Builder[Elem, NewTo] =
 ...
}

Elem是集合中元素的类型,To是生成的集合的类型。使用result()可以从builder中获取到一个集合,之后builder的状态便是未定义的,可以使用clearbuilder的状态重新定义到新的空状态。ArrayBuffer本身就是自己的构造器,使用result会交出本身的buffer


重构共同操作

scala解决这个问题的方式是使用重载,不是Java中的重载形式,依然不够灵活,使用的是带有隐式参数的重载,

def map[B, That](f: Elem => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(this)
for (x <- this) b += f(x)
b.result
}

CanBuildFrom特质可以生成新的集合构建器,From是旧的集合类型,Elem是新的元素类型,To是新的集合类型。

trait CanBuildFrom[-From, -Elem, +To] {
// Creates a new builder
def apply(from: From): Builder[Elem, To]
}

在每一个集合的伴生对象中都定义了隐式的CanBuildFrom对象用于构建新的集合。隐式转换对map这样的操作提供了正确的静态类型信息,但是运行时的类型信息呢,比如说:

scala> val xs: Iterable[Int] = List(1, 2, 3)
xs: Iterable[Int] = List(1, 2, 3)
scala> val ys = xs map (x => x * x)
ys: Iterable[Int] = List(1, 4, 9)

ys的类型也是List类型,这是通过另外的机制实现的。 CanBuildFromapply方法接收一个collection作为入参,可生成泛型遍历器的许多构建器工厂(事实上除了叶子类的构建器工厂)都会将这个apply请求转发至collectiongenericBuilder方法。这个方法进而调用该集合定义时的集合构建器,Scala使用静态的隐式解析来解决map的类型问题,使用虚拟分发来选择与这些类型最匹配的运行时类型。


集成新的序列

另外还有一类是map函数以及++,使用map函数目前返回的是Vector而不是RNA

def map[B, That](f: Elem => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That

Elem是目前集合的元素类型,Bmap函数的返回类型,That是生成的集合类型。That的类型是由隐式参数cbf确定的,所以接下来就是在RNA2的伴生对象中添加一个隐式对象即可。伴生对象canBuildFrom[RNA, Base, RNA],不能放在RNA类中,需要放在RNA的伴生对象中。


集成新的集和映射


集成集合到框架的步骤:

上一篇 下一篇

猜你喜欢

热点阅读