Swift泛型集合类继承时makeIterator()编译错误修复咨询
修复Swift泛型集合子类遍历的编译错误
问题重现
你编写的泛型集合类及子类代码如下:
class StoredCollection<T>: RandomAccessCollection { public fileprivate(set) var items: [T] = [] // RandomAccessCollection public var startIndex: Int { return self.items.startIndex } public var endIndex: Int { return self.items.endIndex } public func index(after i: Int) -> Int { return self.items.index(after: i) } open subscript(index: Int) -> T { get { return self.items[index] } set(newValue) { self.items[index] = newValue } } } class SynchronizedCollection<T>: StoredCollection<T> { } class Event { } let teams: SynchronizedCollection<Event> = SynchronizedCollection() for team in teams { }
遍历teams时触发编译错误:
Referencing instance method 'makeIterator()' on 'Collection' requires
the types 'IndexingIterator' and
'IndexingIterator' be equivalent
问题原因
Swift中,当自定义类型继承RandomAccessCollection但未显式指定Iterator关联类型时,编译器会默认推断迭代器类型为IndexingIterator<Self>。这意味着:
- 父类
StoredCollection<T>的迭代器是IndexingIterator<StoredCollection<T>> - 子类
SynchronizedCollection<T>的迭代器是IndexingIterator<SynchronizedCollection<T>>
这两个迭代器类型属于不同的泛型实例,并不等价,导致遍历调用makeIterator()时类型不匹配,触发编译错误。
修复方案
在父类StoredCollection<T>中显式指定迭代器类型为数组的迭代器(复用底层数组的迭代实现),让父类和子类的迭代器类型保持一致。有两种等价的实现方式:
方式一:显式指定Iterator关联类型
在StoredCollection<T>中添加类型别名,直接复用数组的迭代器:
class StoredCollection<T>: RandomAccessCollection { // 添加这行代码,指定迭代器类型 public typealias Iterator = IndexingIterator<[T]> public fileprivate(set) var items: [T] = [] // RandomAccessCollection public var startIndex: Int { return self.items.startIndex } public var endIndex: Int { return self.items.endIndex } public func index(after i: Int) -> Int { return self.items.index(after: i) } open subscript(index: Int) -> T { get { return self.items[index] } set(newValue) { self.items[index] = newValue } } }
方式二:重写makeIterator()方法
直接返回底层数组的迭代器,覆盖默认的迭代器实现:
class StoredCollection<T>: RandomAccessCollection { public fileprivate(set) var items: [T] = [] // RandomAccessCollection public var startIndex: Int { return self.items.startIndex } public var endIndex: Int { return self.items.endIndex } public func index(after i: Int) -> Int { return self.items.index(after: i) } open subscript(index: Int) -> T { get { return self.items[index] } set(newValue) { self.items[index] = newValue } } // 添加这行代码,返回数组的迭代器 public func makeIterator() -> IndexingIterator<[T]> { return items.makeIterator() } }
两种方式都能让父类和子类的迭代器类型统一为IndexingIterator<[T]>,解决类型不匹配的问题,此时遍历teams就能正常编译执行。
内容的提问来源于stack exchange,提问作者lorenzo
相关产品推荐
相关产品推荐

