用法 一
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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。