If you're willing to have makeIterator be un-overridable, you can make it an extension method instead of a protocol requirement with a default implementation in an extension, and have it return an opaque type:
private struct OrderDictionaryIterator: IteratorProtocol {
let od: any OrderDictionaryProtocol
var index = 0
init(_ od: any OrderDictionaryProtocol) {
self.od = od
}
mutating func next() -> (String, String)? {
guard index < od.keys.count else { return nil }
index += 1
return (od.keys[index], od.values[index])
}
}
protocol OrderDictionaryProtocol: AnyObject, Sequence {
var keys: [String] { get }
var values: [String] { get }
subscript(key: String) -> String { get set }
}
extension OrderDictionaryProtocol {
func makeIterator () -> some IteratorProtocol<(String, String)> {
return OrderDictionaryIterator(self)
}
}
final class OrderedDictionaryBasic: OrderDictionaryProtocol {
private(set) var keys: [String] = []
private(set) var values: [String] = []
subscript(key: String) -> String {
get {
return ""
}
set {
keys.append(key)
values.append(newValue)
}
}
}
Minor correction: makeIterator does not become un-overridable because it is still a protocol requirement of OrderDictionaryProtocol, because OrderDictionaryProtocol inherits it from Sequence. The difference is that makeIterator's return type is Self.Iterator? instead of constrained to only ever be OrderDictionaryIterator?, where the Self.Iterator associated type is specific to each individual conforming type. Types that conform to OrderDictionaryProtocol would by default receive the extension's implementation of makeIterator, making Self.Iterator inferred to be the opaque type.