J'ai tendance à ne mettre que le nécessaire (propriétés stockées, initialisateurs) dans les définitions de mes classes et à déplacer tout le reste dans leurs propres classes. extension
comme une sorte de extension
par bloc logique que je regrouperais avec // MARK:
également.
Pour une sous-classe UIView, par exemple, je me retrouverais avec une extension pour la mise en page, une autre pour la souscription et la gestion des événements, etc. Dans ces extensions, je dois inévitablement surcharger certaines méthodes de UIKit, par ex. layoutSubviews
. Je n'ai jamais remarqué de problèmes avec cette approche - jusqu'à aujourd'hui.
Prenez par exemple cette hiérarchie de classe :
public class C: NSObject {
public func method() { print("C") }
}
public class B: C {
}
extension B {
override public func method() { print("B") }
}
public class A: B {
}
extension A {
override public func method() { print("A") }
}
(A() as A).method()
(A() as B).method()
(A() as C).method()
Le résultat est A B C
. Cela n'a pas beaucoup de sens pour moi. J'ai lu que les extensions de protocole étaient distribuées de manière statique, mais ce n'est pas un protocole. Il s'agit d'une classe ordinaire, et je m'attends à ce que les appels de méthode soient distribués dynamiquement au moment de l'exécution. Il est clair que l'appel sur C
devraient au moins être distribués dynamiquement et produire C
?
Si je supprime l'héritage de NSObject
et faire C
une classe Root, le compilateur se plaint en disant declarations in extensions cannot override yet
que j'ai déjà lu. Mais comment le fait d'avoir NSObject
en tant que classe racine change les choses ?
Déplacer les deux surcharges dans leur déclaration de classe produit A A A
comme prévu, ne se déplaçant que B
Les produits de l'entreprise A B B
en mouvement seulement A
Les produits de l'entreprise C B C
dont la dernière n'a absolument aucun sens pour moi : pas même celle qui est typée statiquement en A
produit le A
-plus de sortie !
Ajout de la dynamic
Le mot-clé dans la définition ou une surcharge semble me donner le comportement désiré "à partir de ce point dans la hiérarchie de la classe"...
Changeons notre exemple pour quelque chose d'un peu moins construit, ce qui m'a fait poster cette question :
public class B: UIView {
}
extension B {
override public func layoutSubviews() { print("B") }
}
public class A: B {
}
extension A {
override public func layoutSubviews() { print("A") }
}
(A() as A).layoutSubviews()
(A() as B).layoutSubviews()
(A() as UIView).layoutSubviews()
Nous obtenons maintenant A B A
. Ici, je ne peux pas rendre dynamique le layoutSubviews de UIView par quelque moyen que ce soit.
En déplaçant les deux surcharges dans leur déclaration de classe, nous obtenons A A A
encore une fois, seulement les A ou seulement les B nous donne toujours A B A
. dynamic
résout à nouveau mes problèmes.
En théorie, je pourrais ajouter dynamic
à tous override
mais j'ai l'impression que je fais quelque chose de mal ici.
Est-ce vraiment mal d'utiliser extension
pour regrouper le code comme je le fais ?
0 votes
Utiliser les extensions de cette manière est une convention pour Swift. Même Apple le fait dans sa bibliothèque standard.
0 votes
github.com/apple/swift/blob/master/docs/
1 votes
@AMomchilov Le document que vous avez lié parle de protocoles, ai-je manqué quelque chose ?
0 votes
Je pense que c'est le même mécanisme qui fonctionne pour les deux.
0 votes
@AMomchilov Mais vous avez dit vous-même que
Using extensions this way is convention for Swift.
-- ça n'a pas de sens que la convention soit rompue.0 votes
Oui, je ne suis pas sûr de savoir pourquoi ça arrive.
0 votes
@ChristianSchnorr
extension
en faisant quelque chose commeadd or replace
,override
ne fonctionnera pas avecextension
.3 votes
Semble faire double emploi Dispatch Swift vers les méthodes surchargées dans les extensions de sous-classes La réponse de Matt est qu'il s'agit d'un bogue (et il cite la documentation à l'appui).