Использование некоторого протокола как конкретного типа, соответствующего другому протоколу, не поддерживается

Я пытаюсь смешивать generics с протоколами, и я получаю очень тяжелое время xD

У меня есть определенная архитектура, реализованная в проекте Android / Java, и я пытаюсь переписать ее, чтобы соответствовать ей в проекте quick / iOS. Но я нашел это ограничение.

ProtocolA

protocol ProtocolA { } 

ProtocolB

 protocol ProtocolB : ProtocolA { } 

ImplementProtocolA

 class ImplementProtocolA 

{ let currentProtocol : P init(currentProtocol : P) { self.currentProtocol = currentProtocol } }

ImplementProtocolB

 class ImplementProtocolB : ImplementProtocolA { } 

Поэтому, когда я пытаюсь установить ProtocolB как конкретный тип, реализующий ProtocolA , я получаю эту ошибку:

Использование «ProtocolB» как конкретного типа, соответствующего протоколу «ProtocolA», не поддерживается

1 Есть ли причина для этого «ограничения»?

2 Есть ли какое-либо обходное решение для реализации этого?

3 Будет ли она поддерживаться в какой-то момент?

–UPDATED–

Другой вариант той же проблемы, я думаю:

Просмотр протоколов

 protocol View { } protocol GetUserView : View { func showProgress() func hideProgress() func showError(message:String) func showUser(userDemo:UserDemo) } 

Протоколы презентатора

 protocol Presenter { typealias V : View } class UserDemoPresenter : Presenter { typealias V = GetUserView } 

Ошибка:

UserDemoPresenter.swift Возможно, соответствие «V» (иначе «GetUserView») не соответствует «View»,

Что это?? Это соответствует!

Даже если я использую View вместо GetUserView, он не компилируется.

 class UserDemoPresenter : Presenter { typealias V = View } 

UserDemoPresenter.swift Возможно, предполагаемое соответствие ‘V’ (aka ‘View’) не соответствует ‘View’

xxDD Я действительно не понимаю.

–UPDATED–

С решением, предложенным Роба Напиром, проблема не исправлена, вместо этого она просто отложена.

Когда вы пытаетесь определить ссылку на UserDemoPresenter, мне нужно указать общий тип, поэтому я получаю ту же ошибку:

 private var presenter : UserDemoPresenter 

Использование GetUserView как конкретного типа, соответствующего протоколу GetUserView, не поддерживается

Основная причина ограничения заключается в том, что Swift не имеет первоclassных метатипов. Самый простой пример – это не работает:

 func isEmpty(xs: Array) -> Bool { return xs.count == 0 } 

Теоретически этот код мог бы работать, и если бы это было сделано, было бы много других типов, которые я мог бы сделать (например, Functor и Monad, которые действительно не могут быть выражены в Swift сегодня). Но вы не можете. Вам нужно помочь Swift прибить это к конкретному типу. Часто мы делаем это с помощью дженериков:

 func isEmpty(xs: [T]) -> Bool { return xs.count == 0 } 

Обратите внимание, что T здесь полностью избыточно. Нет причин, по которым я должен был бы это выразить; он никогда не используется. Но Свифт требует этого, чтобы он мог превратить абстрактный Array в конкретный [T] . То же самое верно и в вашем случае.

Это конкретный тип (ну, это абстрактный тип, который будет превращаться в конкретный тип при его создании и заполнении P ):

 class ImplementProtocolA

Это полностью абстрактный тип, в котором Swift не имеет никакого правила превращаться в конкретный тип:

 class ImplementProtocolB : ImplementProtocolA 

Вы должны сделать это конкретным. Это скомпилирует:

 class ImplementProtocolB : ImplementProtocolA {} 

А также:

 class UserDemoPresenter : Presenter { typealias V = T } 

Просто потому, что вы, вероятно, столкнетесь с проблемой позже: ваша жизнь будет намного легче, если вы создадите эти структуры или final classы. Протоколы микширования, дженерики и polymorphism classов полны очень острыми краями. Иногда вам повезло, и он просто не компилируется. Иногда это будет называть то, чего вы не ожидаете.

Вы можете быть заинтересованы в небольшом уважении к AnySequence, в котором описываются некоторые связанные с этим проблемы.


 private var presenter : UserDemoPresenter 

Это все еще абстрактный тип. Ты имеешь в виду:

 final class Something { private var presenter: UserDemoPresenter } 

Если это создает проблему, вам нужно создать поле. См. Протокол не соответствует самому себе? для обсуждения того, как вы вводите стирание, чтобы вы могли использовать абстрактные типы. Но вам нужно работать в конкретных типах. Вы не можете в конечном счете специализироваться на протоколе. В большинстве случаев вы должны специализироваться на чем-то конкретном.

  • Реализация протокола X-modem в Java
  • Вызывается метод расширения Swift, а не метод, реализованный в подclassе
  • Давайте будем гением компьютера.