Я создаю протокол для абстрагирования различных моделей (созданных вручную, декодируемых и созданных на основе экономии), например:
protocol FeedItemModeling {
var text: String? { get }
var url: URL? { get }
}
protocol FeedModeling {
var items: [FeedItemModeling]? { get }
}
Это будет отлично работать, за исключением того, что модели с экономией не используют basi c массив, но TList
, который, помимо прочего, соответствует RandomAccessCollection
. Поскольку и Array
, и TList
соответствуют RandomAccessCollection
, я пытаюсь изменить определение протокола на:
Попытка A)
var items: RandomAccessCollection<FeedItemModeling>? { get }
, что дает ошибку: " Невозможно специализировать не общий тип c 'RandomAccessCollection'. " Я предполагаю, что это потому, что associatedtype
- это недоработанный дженерик в том смысле, что он может налагать ограничения внутри самого протокола, но не отображается извне; Это означает, что в нашем случае RandomAccessCollection
associatedtypes
разрешаются в пределах RandomAccessCollection
, но у FeedModeling
нет возможности получить к нему доступ?
Попытка B)
var items: RandomAccessCollection? { get }
дает «Протокол 'RandomAccessCollection' может использоваться только как общее c ограничение, потому что у него есть требования к типу Self или связанный с ним» и в любом случае теряет ограничение на FeedItemModeling.
Попытка C)
associatedtype C: RandomAccessCollection
var items: C? { get }
работает, но мы потеряли ограничение на FeedItemModeling
, так что это неприемлемо.
Попытка D)
associatedtype C: RandomAccessCollection
var items: C<FeedItemModeling>? { get }
дает «Невозможно специализировать не-общий c тип 'Self. C'. " Я предполагаю, что это по той же причине, что и выше?
Попытка E)
associatedtype C<E>: RandomAccessCollection where E: FeedItemModeling
var items: C? { get }
дает: «Связанные типы не должны иметь общий список c параметров». Я предполагаю, что это потому, что теперь есть ограничение на ограничение, которое нельзя выразить таким образом?
Попытка F)
typealias C<E> = RandomAccessCollection
var items: C<FeedItemModeling>? { get }
дает: «Протокол 'RandomAccessCollection' можно использовать только как общее c ограничение, потому что оно имеет требования типа Self или связанного типа ". По той же причине?
Попытка G)
associatedtype FeedItemModelingList = RandomAccessCollection where RandomAccessCollection.Element: FeedItemModeling
var items: FeedItemModelingList? { get }
дает: «Связанный тип« Элемент »может использоваться только с конкретным типом или базой параметров c». Я не понимаю этого; пожалуйста, дайте мне знать, почему?
Попытка H)
protocol FeedItemModelingList: RandomAccessCollection {}
...
var items: FeedItemModelingList? { get }
дает: «Протокол 'FeedItemModelingList' может использоваться только в качестве общего c ограничения, поскольку он имеет требования типа Self или связанные с ним ".
Попытка I)
protocol FeedItemModelingList: RandomAccessCollection where Element == FeedItemModeling {}
...
associatedtype L = FeedItemModelingList
var items: L? { get }
кажется, работает (пока), но действительно некрасиво.
Есть идея получше?