【发布时间】:2020-08-04 16:18:36
【问题描述】:
我正在创建一个协议来抽象不同的模型(手工制作、可解码和节俭生成),如下所示:
protocol FeedItemModeling {
var text: String? { get }
var url: URL? { get }
}
protocol FeedModeling {
var items: [FeedItemModeling]? { get }
}
这会很好用,除了 thrift 模型不使用基本数组,而是使用符合 RandomAccessCollection 的 TList 等等。由于Array 和TList 都符合RandomAccessCollection,我正在尝试将协议定义更改为:
尝试 A)
var items: RandomAccessCollection<FeedItemModeling>? { get }
这给出了错误:“不能专门化非泛型类型 'RandomAccessCollection'。”我认为这是因为associatedtype 是一个半生不熟的泛型,因为它可以在协议本身内部强制执行约束,但不会暴露在外部;这意味着在我们的例子中,RandomAccessCollection 的associatedtypes 在RandomAccessCollection 内解析,但FeedModeling 无法访问它?
尝试 B)
var items: RandomAccessCollection? { get }
给出“Protocol 'RandomAccessCollection' 只能用作通用约束,因为它具有 Self 或关联的类型要求”并且无论如何都会失去对 FeedItemModeling 的约束。
尝试 C)
associatedtype C: RandomAccessCollection
var items: C? { get }
有效,但我们失去了对 FeedItemModeling 的约束,所以这是不可接受的。
尝试 D)
associatedtype C: RandomAccessCollection
var items: C<FeedItemModeling>? { get }
给出“不能专门化非泛型类型‘Self.C’。”我想是和上面一样的原因吧?
尝试 E)
associatedtype C<E>: RandomAccessCollection where E: FeedItemModeling
var items: C? { get }
给出“关联类型不能有泛型参数列表”。我猜是因为现在约束上有个约束,不能这样表达?
尝试 F)
typealias C<E> = RandomAccessCollection
var items: C<FeedItemModeling>? { get }
给出:“协议 'RandomAccessCollection' 只能用作通用约束,因为它具有 Self 或关联的类型要求”。同样的原因?
尝试 G)
associatedtype FeedItemModelingList = RandomAccessCollection where RandomAccessCollection.Element: FeedItemModeling
var items: FeedItemModelingList? { get }
给出“关联类型‘元素’只能与具体类型或泛型参数库一起使用”。我不明白这个;请告诉我为什么?
尝试 H)
protocol FeedItemModelingList: RandomAccessCollection {}
...
var items: FeedItemModelingList? { get }
给出:“协议 'FeedItemModelingList' 只能用作通用约束,因为它具有 Self 或关联的类型要求”。
尝试一)
protocol FeedItemModelingList: RandomAccessCollection where Element == FeedItemModeling {}
...
associatedtype L = FeedItemModelingList
var items: L? { get }
似乎工作(到目前为止),但真的很丑。
有更好的主意吗?
【问题讨论】:
标签: swift generics collections protocols