J'ai tendance à ne mettre que les nécessités (propriétés stockées, initialiseurs) dans mes définitions de classe et à déplacer tout le reste dans les leurs extension, un peu comme un extensionbloc logique avec lequel je grouperais // MARK:également.
Pour une sous-classe UIView par exemple, je finirais avec une extension pour les trucs liés à la mise en page, une pour l'abonnement et la gestion des événements, etc. Dans ces extensions, je dois inévitablement remplacer certaines méthodes UIKit, par exemple layoutSubviews. Je n'ai jamais remarqué de problèmes avec cette approche - jusqu'à aujourd'hui.
Prenez cette hiérarchie de classes par exemple:
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()
La sortie est A B C. Cela n'a pas de sens pour moi. J'ai lu que les extensions de protocole étaient distribuées statiquement, mais ce n'est pas un protocole. Il s'agit d'une classe régulière, 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 en cours Cdevrait au moins être distribué et produit de manière dynamique C?
Si je supprime l'héritage NSObjectet crée Cune classe racine, le compilateur se plaint en disant declarations in extensions cannot override yet, ce que j'ai déjà lu. Mais comment le fait d'avoir NSObjectcomme classe racine change-t-il les choses?
Déplacer les deux surcharges dans leur déclaration de classe produit A A Acomme prévu, déplacer uniquement Bles produits A B B, déplacer uniquement Ales produits C B C, dont le dernier n'a absolument aucun sens pour moi: même pas celui typé statiquement pour Aproduire le A-output!
L'ajout du dynamicmot - clé à la définition ou un remplacement semble me donner le comportement souhaité `` à partir de ce point dans la hiérarchie des classes vers le bas '' ...
Changeons notre exemple en quelque chose d'un peu moins construit, ce qui m'a fait poser 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 en aucun cas rendre le layoutSubviews de UIView dynamique.
Déplacer les deux remplacements dans leur déclaration de classe nous A A Aramène, seuls les A ou seulement les B nous obtiennent encore A B A. dynamicrésout à nouveau mes problèmes.
En théorie, je pourrais ajouter dynamicà tout ce que overrideje fais mais j'ai l'impression de faire quelque chose de mal ici.
Est-ce vraiment mal d'utiliser extensions pour grouper du code comme je le fais?