web-dev-qa-db-fra.com

Pour quelles raisons utiliseriez-vous une extension de classe distincte pour chaque délégué à Swift?

Je travaillais à travers un tutoriel de Ray Wenderlich et remarquais que l'auteur utilise des extensions de classe pour tenir des rappels délégués plutôt que de les avoir manipulés dans la classe elle-même .:

Déléguez les rappels à l'intérieur de l'extension de classe :

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

par opposition à l'avoir contenue dans la classe:

Déléguez des rappels à l'intérieur de la classe :

class LogsViewController : UITableViewController, UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

J'ai trouvé cet étrange et intéressant en même temps. Il possède un fichier dédié juste aux extensions de la classe LogsviewController nommée "LogsviewControllerextension.swift" et dispose d'une extension différente pour chaque protocole de délégué: UitablesViewAsource, UisplitViewDelegate, etc I.e.:

extensions de classe multiples chacune avec les rappels de délégués dans son propre fichier :

extension LogsViewController: UISplitViewControllerDelegate {
    ... callbacks
}

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    ... callbacks
}

Pourquoi?

Quels avantages sont là pour faire cela? Je peux voir où il pourrait être un peu plus lisible pour séparer cela, mais en même temps, il s'agit d'un niveau d'indirection. Existe-t-il OO Principes qui soutiennent ou contre cela?

13
morbidhawk

Je ne sais pas pourquoi vous avez dit qu'il ajoute un niveau d'indirection. Peut-être que vous voulez dire quelque chose de différent de celui que le sens traditionnel, car il n'y a pas d'indirecte supplémentaire créée en faisant cela. Mais pourquoi le faire?

Je le fais parce qu'il est plus modulaire. Tout le code requis par l'interface est regroupé en une seule place (à l'exception des propriétés réelles.) Si je choisis plus tard de faire une classe distincte pour mettre en œuvre ce protocole (et introduire ainsi un niveau d'indirection réel) Tout ce que j'ai besoin de FAIT Changez l'extension en une classe de ses propres (transmettre les propriétés nécessaires à travers une fonction init) et créer une propriété sur la vue ViewController pour instancier l'objet.

J'ai également mis toutes les fonctions privées qui ne sont utilisées que par les fonctions de ce protocole dans l'extension. Je ne suis pas allé jusqu'à créer un fichier complètement séparé pour l'extension, mais cela indique clairement que ces fonctions privées ne sont que pour ce protocole.

Et en tout état de cause, les personnes se plaignent souvent de contrôleurs de la graisse et de briser un contrôleur d'affichage de cette manière permet de mieux le garder mieux organisé, même s'il ne rend pas le contrôleur d'affichage plus mince.

15
Daniel T.

Comme Daniel a dit en ce qui concerne l'indirection, il n'y a pas de niveau de celui-ci.
[.____] Je suis d'accord avec lui et j'aimerais ajouter une fonctionnalité extra puissante des extensions de protocole que je connaissais récemment.

Dites que vous avez un protocole didCopyText par exemple. Vous allez mettre en œuvre cela comme suit:

protocol didCopyText {
  var charachtersCount: Int {get}
  func addToClipboardWith(text: String)
}

Dans Swift, les propriétés et les méthodes ne sont pas implémentées dans la déclaration de protocole, vous souhaiteriez écrire la mise en œuvre dans chaque classe conforme à la didCopyText, avec un nombre incrémental de classes conformes à ce protocole avec la même mise en œuvre, elle serait se retrouver avec juste un code répété en désordre. C'est là que les extensions de protocole sont utiles.

protocol didCopyText {
var charachtersCount: Int {
    get {
     // implementation
    }
}
func addToClipboardWith(text: String) {
      // implementation
 }
}

Avec la mise en œuvre des propriétés et des méthodes du protocole. Maintenant, toute classe est conforme à ce protocole, utilisera la même mise en œuvre.

2
MEnnabah

Disons que votre classe prend en charge trois protocoles et vous devez donc ajouter trois séries de fonctions. Le seul but de ces fonctions est de soutenir un protocole, de sorte que vous avez besoin de la documentation.

Toutefois, si vous ajoutez une extension pour chaque protocole et que, dans chaque extension, vous implémentez exactement les fonctions nécessaires à ce protocole, qui rend votre code beaucoup plus lisible.

Je ne les placerais probablement pas dans des fichiers séparés à moins que ces extensions soient vraiment importantes.

1
gnasher729