用法 一
trait IsIterable[Repr] extends IsIterableOnce[Repr]
定义扩展方法时可用于避免代码重复的特征,这些扩展方法应该适用于现有的 Scala 集合(即扩展 Iterable
的类型)以及可以转换为 Scala 的其他(可能是用户定义的)类型集合类型.这个特性使得处理 Scala 集合和可以统一隐式转换为集合类型的类型成为可能。例如,可以提供适用于集合类型和 String
的扩展方法( String
不扩展 Iterable
,但可以转换为 Iterable
)
IsIterable
提供三个成员:
1. 类型成员 A
,表示目标的元素类型 Iterable[A]
1. 类型成员 C
,表示保留集合元素类型的转换操作返回的类型 1. 方法 apply
,它提供一种在我们希望添加扩展方法的类型之间进行转换的方法,Repr
和 IterableOps[A, Iterable, C]
。
用法
必须提供IsIterable
作为隐式转换的隐式参数类型。它的用法如下所示。我们在以下示例中的目标是为任何扩展或可以转换为 Iterable
的类型提供通用扩展方法 mapReduce
。在我们的示例中,这包括 String
。
import scala.collection.{Iterable, IterableOps}
import scala.collection.generic.IsIterable
class ExtensionMethods[Repr, I <: IsIterable[Repr]](coll: Repr, it: I) {
def mapReduce[B](mapper: it.A => B)(reducer: (B, B) => B): B = {
val iter = it(coll).iterator
var res = mapper(iter.next())
while (iter.hasNext)
res = reducer(res, mapper(iter.next()))
res
}
}
implicit def withExtensions[Repr](coll: Repr)(implicit it: IsIterable[Repr]): ExtensionMethods[Repr, it.type] =
new ExtensionMethods(coll, it)
// See it in action!
List(1, 2, 3).mapReduce(_ * 2)(_ + _) // res0: Int = 12
"Yeah, well, you know, that's just, like, your opinion, man.".mapReduce(x => 1)(_ + _) // res1: Int = 59
在这里,我们首先创建一个类ExtensionMethods
,其中包含我们的mapReduce
扩展方法。
请注意,ExtensionMethods
采用 Repr
类型的构造函数参数 coll
,其中 Repr
表示(通常)集合类型,以及 IsIterable[Repr]
子类型的参数 it
。该方法的主体首先将coll
参数转换为IterableOps
,以便在其上调用iterator
方法。其余的实现很简单。
withExtensions
隐式转换使mapReduce
操作可用于任何类型Repr
,它存在隐式IsIterable[Repr]
实例。请注意我们如何通过使用 it.type
单例类型而不是更广泛的 IsIterable[Repr]
类型来跟踪隐式 it
参数的精确类型。我们这样做是为了不丢失it
参数的类型成员A
和C
携带的信息。
当 mapReduce
方法在某些类型上调用它不是它的成员时,会触发隐式搜索。因为隐式转换 withExtensions
是通用的,所以只要可以找到类型为 IsIterable[Repr]
的隐式值,就会应用它。鉴于 IsIterable
伴随对象包含返回类型为 IsIterable
的值的隐式成员,通常会满足此要求,并且将上一段中说明的交互链设置为行动。 (请参阅 IsIterable
伴随对象,其中包含可用隐式的精确规范。)
注意: 目前,由于类型推断的限制,无法将隐式转换和类与扩展方法组合成一个隐式类。
为新类型实现IsIterable
必须简单地提供特定于新类型的IsIterable
类型的隐式值,或者返回特定于新类型的IsIterable
实例的隐式转换。
下面是 IsIterable
特征的实现示例,其中 Repr
类型为 Range
。
implicit val rangeRepr: IsIterable[Range] { type A = Int; type C = IndexedSeq[Int] } =
new IsIterable[Range] {
type A = Int
type C = IndexedSeq[Int]
def apply(coll: Range): IterableOps[Int, IndexedSeq, IndexedSeq[Int]] = coll
}
(注意在实践中IsIterable[Range]
实例已经由标准库提供,它被定义为IsSeq[Range]
实例)
伴生:
- object
源码:
- IsIterable.scala
相关用法
- Scala generic.IsIterableOnce用法及代码示例
- Scala Tabulate.sliding用法及代码示例
- Scala ArrayBuffer.inits用法及代码示例
- Scala long.BitwiseOr用法及代码示例
- Scala StringBuilder.partitionMap用法及代码示例
- Scala List distinct()用法及代码示例
- Scala DefaultMap.sizeIs用法及代码示例
- Scala StrictOptimizedIterableOps.sliding用法及代码示例
- Scala Searching.SearchResult用法及代码示例
- Scala ::.collectFirst用法及代码示例
- Scala TreeSet diff()用法及代码示例
- Scala Char getClass()用法及代码示例
- Scala int.Min用法及代码示例
- Scala IntMap.groupMap用法及代码示例
- Scala Map3.mkString用法及代码示例
- Scala IterableOnceOps.flatMap用法及代码示例
- Scala IndexedSeqOps.lengthIs用法及代码示例
- Scala Map3.addString用法及代码示例
- Scala WrappedString.scanRight用法及代码示例
- Scala String compareToIgnoreCase()用法及代码示例
- Scala List drop()用法及代码示例
- Scala ofDouble.inits用法及代码示例
- Scala SortedSet.tails用法及代码示例
- Scala String replaceFirst()用法及代码示例
- Scala StringView.groupMap用法及代码示例
注:本文由纯净天空筛选整理自scala-lang.org大神的英文原创作品 generic.IsIterable。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。