Как создать протокол с универсальным свойством c, подобным массиву - PullRequest
0 голосов
/ 04 августа 2020

Я создаю протокол для абстрагирования различных моделей (созданных вручную, декодируемых и созданных на основе экономии), например:

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 }

кажется, работает (пока), но действительно некрасиво.

Есть идея получше?

...