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

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


 override func makeIterator() -> IteratorImpl {
 return IteratorImpl(seq.makeIterator())
 }

}

我们需要一种方法来实际创建这些东西:对 MAnySequence 添加一个静态方法,该方法创建一个 MAnySequenceImpl 实例,并将其作为 MAnySequence 类型返回给调用者。


extension MAnySequence {
 static func make<Seq: Sequence>(_ seq: Seq) -> MAnySequence<Element> where Seq.Element == Element {
 return MAnySequenceImpl<Seq>(seq)
 }
}

在实际开发中,我们可能会做一些额外的操作来让 MAnySequence 提供一个初始化方法。

我们来试试 MAnySequence:


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

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

完美!

基于函数的类型擦除

有时我们希望对外暴露支持多种类型的方法,但又不想指定具体的类型。一个简单的办法就是,存储那些签名仅涉及到我们想公开的类型的函数,函数主体在底层已知具体实现类型的上下文中创建。

我们一起看看如何运用这种方法来设计 MAnySequence,与前面的实现很类似。它是一个结构体而非类,这是因为它仅仅作为容器使用,不需要有任何的继承关系。


struct MAnySequence<Element>: Sequence {

跟之前一样,MAnySequence 也需要一个可返回的迭代器(Iterator)。迭代器同样被设计为结构体,并持有一个参数为空并返回 Element? 的存储型属性,实际上这个属性是一个函数,被用于 IteratorProtocol 协议的 next 方法中。接下来 Iterator 遵循 IteratorProtocol 协议,并在 next 方法中调用函数: