Swift如何使用类型擦除及自定义详解

2020-01-09 00:16:13王冬梅


struct Iterator: IteratorProtocol {
 let _next: () -> Element?

 func next() -> Element? {
  return _next()
 }
}

MAnySequence 与 Iterator 很相似:持有一个参数为空返回 Iterator 类型的存储型属性。遵循 Sequence 协议并在 makeIterator 方法中调用这个属性。


let _makeIterator: () -> Iterator

func makeIterator() -> Iterator {
 return _makeIterator()
}

MAnySequence 的构造函数正是魔法起作用的地方,它接收任意序列作为参数:


init<Seq: Sequence>(_ seq: Seq) where Seq.Element == Element {

接下来需要在构造函数中包装此序列的功能:


_makeIterator = {

如何生成迭代器?请求 Seq 序列生成:


var iterator = seq.makeIterator()

接下来我们利用自定义的迭代结构体包装序列生成的迭代器,包装后的 _next 属性将会在迭代器协议的 next() 方法中被调用:


   return Iterator(_next: { iterator.next() })
  }
 }
}

接下来展示如何使用 MAnySequence:


func printInts(_ seq: MAnySequence<Int>) {
 for elt in seq {
  print(elt)
 }
}

let array = [1, 2, 3, 4, 5]
printInts(MAnySequence(array))
printInts(MAnySequence(array[1 ..< 4]))

正确运行,太棒了!

当需要将小部分功能包装为更大类型的一部分时,这种基于函数的类型擦除方法特别实用,这样做就不需要有单独的类来实现被擦除类型的这部分功能了。

比方说你现在想要编写一些适用于各种集合类型的代码,但它真正需要能够对这些集合执行的操作是获取计数并执行从零开始的整数下标。如访问 tableView 数据源。它可能看起来像这样: