У меня есть следующий код
enum AppSubscription<Event>: Subscription {
func map<ParentSubscription>(_ lift: @escaping (Event) -> (ParentSubscription.Event)) -> ParentSubscription where ParentSubscription: Subscription {
switch self {
case let .loadedArticles(cb):
return AppSubscription<ParentSubscription.Event>.loadedArticles { article, isHot in lift(cb(article, isHot)) } as! ParentSubscription
case let .savedArticles(cb):
return AppSubscription<ParentSubscription.Event>.savedArticles { article in lift(cb(article)) } as! ParentSubscription
case let .deletedArticles(cb):
return AppSubscription<ParentSubscription.Event>.deletedArticles { article in lift(cb(article)) } as! ParentSubscription
}
}
case loadedArticles((Article, Bool) -> Event)
case savedArticles((Article) -> Event)
case deletedArticles((Article) -> Event)
}
, и я хочу создать протокол для Subscription
(которому соответствует AppSubscription
). Это моя попытка
public protocol Subscription {
associatedtype Event
func map<ParentSubscription>(_ lift:
@escaping (Event) -> (ParentSubscription.Event)) -> ParentSubscription where
ParentSubscription: Subscription
}
, но я получаю ошибки
Subs.playground:21:31: Protocol 'Subscription' can only be used as a generic constraint because it has Self or associated type requirements
и
Subs.playground:21:28: Same-type requirement makes generic parameter 'ParentSubscription' non-generic
Как мне записать функцию протокола map
в соответствует реализации в AppSubscription
?
Изменить : переключено на ParentSubscription: Subscription
согласно предложению @ Fabian. Также добавлены недостающие @escaping
в AppSubscription.
С изменениями я не уверен, как согласовать протокол с реализацией. Если я использую подпись точно так, как написано в протоколе
func map<ParentSubscription, ParentEvent>(_ lift: @escaping (Event) -> (ParentEvent)) -> ParentSubscription where ParentSubscription : Subscription, ParentEvent == ParentSubscription.Event {
, я вынужден использовать as! ParentSubscription
, что кажется избыточным. Если я использую подпись
func map<ParentEvent>(_ lift: (Event) -> ParentEvent) -> AppSubscription<ParentEvent> {
, он жалуется, что AppSubscription
не соответствует протоколу. Это единственный способ заставить его скомпилировать для использования as!
?
Edit2 : удален избыточный ParentEvent
и заменен на ParentSubscription.Event
согласно другому предложению @Fabian .
Теперь код компилируется, и это здорово, и большое спасибо @Fabian.
Я думаю, будет справедливо сказать, что количество подсказок типа кажется неудобным, есть ли способ избежать или сократить какое-либо из них?
Edit3 : Добавление реплики https://repl.it/@opsb / ScratchyTrustworthyArchitect , чтобы упростить игру.