Supposons que nous ayons l'exemple de code suivant:
protocol MyProtocol {
func someFunction()
}
public class MyClass {
}
public extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
La compilation du code ci-dessus génère l'erreur suivante:
Erreur: le modificateur 'public' ne peut pas être utilisé avec des extensions qui déclarent des conformités de protocole
La même chose se produit si je marque l'extension avec private
. Il semble que vous ne puissiez pas définir le niveau d'accès d'une extension conforme à un protocole, quel que soit le niveau d'accès défini. Même définir la déclaration de protocole sur public
ou private
ne supprime pas l'erreur.
Quelle est la raison pour laquelle Swift restreint de cette manière le niveau d'accès d'une extension si celle-ci est conforme à un protocole? Si la conformité de protocole est appliquée au niveau de la classe, cette restriction n’existe pas.
Si j'obéis au compilateur et supprime la désignation private
/public
, quel est le niveau d'accès de someFunction()
?
extension MyClass: MyProtocol {
func someFunction() {
print("hello")
}
}
J'imagine que dans ce cas, cela suivrait la mise en œuvre MyClass
originale et serait public
mais je ne suis pas sûr.
Ce comportement existe-t-il parce qu'une conformité de protocole dans une extension signifie que toute la classe est conforme au protocole et qu'il est donc redondant de redéfinir le niveau d'accès dans l'extension?
C'est parce qu'il est impossible de se conformer à un protocole à un niveau d'accès autre que le niveau d'accès du protocole lui-même. En d'autres termes, si vous avez un protocole public
, vous ne pouvez pas y être conforme private
. Ceci est dû en partie au fait que la conformité de protocole est une question qui peut être interrogée au moment de l’exécution (et ne peut donc pas différer entre le module dans lequel vous vous trouvez, ou qui doit être implémentée deux fois dans différents fichiers/modules), et en partie parce que cela serait simplement étrange si un type conforme à un protocole dans un fichier et non conforme à ce protocole lorsqu'il est utilisé dans d'autres fichiers.
Quant à votre question sur le niveau d’accès de someFunction
, elle suit les mêmes règles que toute autre fonction. Ce qui revient à dire que la valeur par défaut est internal
, à moins que le type lui-même ait un niveau d'accès inférieur. Ainsi, dans votre cas, si MyClass
et MyProtocol
sont tous les deux public
, vous pouvez vous attendre à obtenir une erreur du compilateur vous indiquant que someFunction()
doit également être marqué public
. Mais comme il semble que MyProtocol
est en fait internal
, le fait d’omettre tout modificateur d’accès fonctionne comme someFunction()
par défaut à internal
.
Si j'obéis au compilateur et supprime la désignation privé/public, quel est le niveau d'accès de
someFunction()?
Quoi que vous disiez c'est. Rien ne vous empêche de marquer le niveau d'accès de someFunction()
. Mais dans ce cas, vous ne pouvez pas le marquer comme private
, car le niveau d'accès de MyProtocol est internal
.
La valeur par défaut est donc internal
dans votre code. Rien n'est jamais public
par défaut; public
est toujours une désignation explicitement opt-in.
La conformité privée pourrait enfreindre Principe de substitution de Liskov
En citant un résumé du forum Apple devloper, répondez à une question similaire:
"La chose la plus importante que j'ai notée à propos de la conformité privée, en particulier parmi les classes destinées à être sous-classées, est que vous vous retrouvez souvent avec des implémentations contradictoires."
Par exemple, vous avez une classe qui se conforme de manière privée à un protocole et implémente toutes ses méthodes. Plus tard, une sous-classe arrive et veut faire la même chose, mais veut seulement implémenter les méthodes requises (car celles optionnelles non implémentées peuvent fournir un comportement par défaut que la sous-classe souhaite). Mais maintenant vous avez 2 problèmes:
1) L'objet en attente de cette implémentation de protocole a maintenant éventuellement 2 consommateurs du protocole sur le même objet. Cela conduit les deux objets à se prémunir contre les appels inattendus. Ou aucune, car, en raison de la conformité privée, la sous-classe ne peut pas appeler super pour résoudre les appels inattendus.
2) Il n’existe aucun moyen pour la sous-classe d’obtenir le comportement qu’elle souhaite sans modifier le protocole, l’implémentation de la super-classe ne pouvant être supprimée sans affecter son comportement.