Il n'y a pas vraie raison pour laquelle cela ne devrait pas être possible, en lecture seule exigence de propriété peut être covariant, en retournant un ConformsToB
exemple d'une propriété typée comme ProtocolB
est parfaitement légal.
Swift ne le supporte pas actuellement. Pour ce faire, le compilateur doit générer a thunk entre la table des témoins du protocole et l'implémentation conforme afin d'effectuer la (les) conversion (s) de type nécessaire (s). Par exemple, une instance ConformsToB
doit être encadréein an existential container afin d'être tapée comme ProtocolB
(et l'appelant ne peut pas le faire car il ne sait rien de l'implémentation appelée).
Mais encore une fois, il n'y a aucune raison que le compilateur ne puisse pas faire cela. Il y a plusieurs rapports de bugs ouverts sur ce, this one qui est spécifique à la lecture seule des exigences de propriété et this general one, dans lequel Slava Pestov, membre de l'équipe Swift, dit:
[...] nous voulons les témoins de protocole et la méthode remplacent dans tous les cas où une conversion de fonction est autorisée
Cela ressemble vraiment à quelque chose que l'équipe Swift cherche à implémenter dans une future version du langage.
Dans le même temps cependant, comme @BallpointBen says, une solution consiste à utiliser un associatedtype
:
protocol ProtocolA {
// allow the conforming type to satisfy this with a concrete type
// that conforms to ProtocolB.
associatedtype SomeProperty : ProtocolB
var someProperty: SomeProperty { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA {
// implicitly satisfy the associatedtype with ConformsToB.
var someProperty: ConformsToB
init(someProperty: ConformsToB) {
self.someProperty = someProperty
}
}
Mais cela est tout à fait insatisfaisante, car cela signifie que ProtocolA
n'est plus utilisable comme un type (parce qu'il a associatedtype
exigences). Cela change aussi ce que dit le protocole. A l'origine, il a dit que someProperty
pourrait retourner quoi que ce soit qui était conforme à ProtocolB
- maintenant il est dit qu'une mise en œuvre de someProperty
traite avec un seul type concret spécifique qui est conforme à ProtocolB
.
Une autre solution est juste pour définir une propriété fictive afin de satisfaire à l'exigence de protocole:
protocol ProtocolA {
var someProperty: ProtocolB { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA {
// dummy property to satisfy protocol conformance.
var someProperty: ProtocolB {
return actualSomeProperty
}
// the *actual* implementation of someProperty.
var actualSomeProperty: ConformsToB
init(someProperty: ConformsToB) {
self.actualSomeProperty = someProperty
}
}
Ici, nous écrivons essentiellement thunk pour le compilateur - mais il est pas particulièrement agréable car il ajoute une propriété inutile à l'API.
Merci pour les liens. C'est malheureux, mais bon à savoir! – solidcell
Si vous voulez ce comportement, dans 'ProtocolA', vous devriez avoir' associatedtype T: ProtocolB' et ensuite déclarer 'var someProperty: T {get}' – BallpointBen
Cela fonctionnerait comme solution de contournement entre temps jusqu'à ce qu'il soit (espérons-le) corrigé, mais Je suis vraiment hésitant à ajouter un type associé, car cela ferait bouillir cette connaissance dans le reste du graphe d'objets, qui devient rapidement incontrôlable. – solidcell