Использование некоторого протокола как конкретного типа, соответствующего другому протоколу, не поддерживается
Я пытаюсь смешивать generics с протоколами, и я получаю очень тяжелое время xD
У меня есть определенная архитектура, реализованная в проекте Android / Java, и я пытаюсь переписать ее, чтобы соответствовать ей в проекте quick / iOS. Но я нашел это ограничение.
ProtocolA
- Использование в качестве конкретного типа, соответствующего протоколу AnyObject, не поддерживается
- Простой последовательный протокол связи «точка-точка»
- В чем разница между источником данных и делегатом?
- Регистрация и использование пользовательского протокола java.net.URL
- Разница между TCP и UDP?
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, не поддерживается
- Почему я не могу передать Protocol.Type на общий параметр T.Type?
- Ошибки данных URI и ошибки Internet Explorer 9
- Как объявить переменную, которая имеет тип и реализует протокол?
- Почему писать закрытый TCP-разъем хуже, чем читать?
- NSNotificationCenter против делегирования (используя протоколы)?
- доступ к файлу с использованием Java с Samba JCIFS
- Android / iOS - настройка пользовательского URI / протокола
- Формат данных GWT RPC
Основная причина ограничения заключается в том, что 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 }
Если это создает проблему, вам нужно создать поле. См. Протокол не соответствует самому себе? для обсуждения того, как вы вводите стирание, чтобы вы могли использовать абстрактные типы. Но вам нужно работать в конкретных типах. Вы не можете в конечном счете специализироваться на протоколе. В большинстве случаев вы должны специализироваться на чем-то конкретном.