L’utilisation d’un protocole comme type concret conforme à un autre protocole n’est pas prise en charge

J’essaie de mélanger des génériques avec des protocoles et je commence à avoir un temps très dur

J’ai une certaine architecture implémentée dans un projet Android / Java et j’essaie de la réécrire pour l’adapter à un projet swift / iOS. Mais j’ai trouvé cette limitation.

ProtocoleA

protocol ProtocolA { } 

ProtocoleB

 protocol ProtocolB : ProtocolA { } 

ImplementProtocolA

 class ImplementProtocolA 

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

ImplementProtocolB

 class ImplementProtocolB : ImplementProtocolA { } 

Donc, quand j’essaie de définir ProtocolB comme type concret qui implémente ProtocolA , j’obtiens cette erreur:

L’utilisation de ‘ProtocolB’ comme type concret conforme au protocole ‘ProtocolA’ n’est pas prise en charge

1 Y a-t-il une raison à cette «limitation»?

2 Y a-t-il une solution de rechange pour que cela soit implémenté?

3 Sera-t-il pris en charge à un moment donné?

–ACTUALISÉ–

Une autre variante du même problème, je pense:

Voir les protocoles

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

Protocoles de présentation

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

Erreur:

UserDemoPresenter.swift Peut-être que la correspondance voulue ‘V’ (aka ‘GetUserView’) n’est pas conforme à ‘View’

Qu’est-ce que c’est?? C’est conforme!

Même si j’utilise View au lieu de GetUserView, il ne comstack pas.

 class UserDemoPresenter : Presenter { typealias V = View } 

UserDemoPresenter.swift La correspondance éventuellement voulue ‘V’ (aka ‘View’) n’est pas conforme à ‘View’

xxDD Je ne comprends pas vraiment.

–ACTUALISÉ–

Avec la solution proposée par Rob Napier, le problème n’est pas résolu, il est simplement retardé.

Quand j’essaie de définir une référence à UserDemoPresenter, je dois spécifier le type générique, donc j’obtiens la même erreur:

 private var presenter : UserDemoPresenter 

L’utilisation de ‘GetUserView’ comme type concret conforme au protocole ‘GetUserView’ n’est pas prise en charge

La raison sous-jacente de cette limitation est que Swift n’a pas de métatypes de première classe. L’exemple le plus simple est que cela ne fonctionne pas:

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

En théorie, ce code pourrait fonctionner, et si c’était le cas, il y aurait beaucoup d’autres types que je pourrais créer (comme Functor et Monad, qui ne peuvent vraiment pas être exprimés dans Swift aujourd’hui). Mais tu ne peux pas. Vous devez aider Swift à clouer ceci jusqu’à un type concret. Nous faisons souvent cela avec des génériques:

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

Notez que T est totalement redondant ici. Il n’y a pas de raison que je devrais l’exprimer; il n’est jamais utilisé Mais Swift en a besoin pour pouvoir transformer le Array abstrait en béton [T] . La même chose est vraie dans votre cas.

C’est un type concret (enfin, c’est un type abstrait qui sera transformé en un type concret chaque fois qu’il est instancié et que P est rempli):

 class ImplementProtocolA

Ceci est un type totalement abstrait que Swift n’a aucune règle à transformer en un type concret:

 class ImplementProtocolB : ImplementProtocolA 

Vous devez le rendre concret. Cela comstackra:

 class ImplementProtocolB : ImplementProtocolA {} 

Et aussi:

 class UserDemoPresenter : Presenter { typealias V = T } 

Juste parce que vous êtes susceptible de rencontrer le problème plus tard: votre vie ira beaucoup plus facile si vous faites ces structures ou les classes final . Les protocoles de mélange, les génériques et le polymorphism de classe sont remplis de bords très nets. Parfois, vous avez de la chance et cela ne va tout simplement pas se comstackr. Parfois, cela appellera des choses auxquelles vous ne vous attendez pas.

Vous pourriez être intéressé par Un peu de respect pour AnySequence qui détaille certaines questions connexes.


 private var presenter : UserDemoPresenter 

Ceci est toujours un type abstrait. Vous voulez dire:

 final class Something { private var presenter: UserDemoPresenter } 

Si cela crée un problème, vous devrez créer une boîte. Voir le protocole n’est pas conforme à lui-même? pour discuter de la façon dont vous tapez, vous pouvez donc contenir des types abstraits. Mais vous devez travailler sur des types concrets. Vous ne pouvez finalement pas vous spécialiser sur un protocole. Vous devez éventuellement vous spécialiser sur quelque chose de concret dans la majorité des cas.