Closures: définition, utilité

pendant que le sujet est d'actualité.


 


Je bute un peu (voir beaucoup !) sur la philosophie de la/le "Closure".


 


Quelles en sont les contraintes, les cas d'intérêt, les avantages, les limites ?

Réponses

  • CéroceCéroce Membre, Modérateur

    Je bute un peu (voir beaucoup !) sur la philosophie de la/le "Closure".



    Déjà , c'est exactement la même chose que les "blocs" d'Objective-C.

    En gros, une closure est une fonction, la différence est qu'elle capture son environnement lorsqu'on la crée.

    Ainsi, si la variable v vaut 10 à  la création de la closure, et que tu fixes ensuite v = 20, quand la closure s'exécutera, v vaudra toujours 10.

     



    Quelles en sont les contraintes



    La contrainte la plus fréquente est que comme la closure capture son environnement, alors si tu utilises self dedans, self va être retenu " au sens de la gestion mémoire.

    ça crée un tas de problèmes. Par exemple si la closure est gardée dans une propriété strong et qu'elle fait appel à  self, la closure et self se retiennent mutuellement, et on a un memory leak.

    Souvent, il faudra donc écrire { [weak self] in ... } dans la closure. C'était déjà  le cas en ObjC.

     



    les cas d'intérêt



    La closure peut être stockée dans une variable. => On peut l'appeler plus tard.

    Passée en paramètre => On peut paramétrer le comportement d'une fonction.

     



    les avantages



    Le premier avantage pour nous en Cocoa est que ça évite d'utiliser la délégation. Un cas typique est celui des requêtes réseau: NSURLConnection/Session va lancer la requête mais tu auras le résultat quelques ms plus tard.


    En travaillant par délégation, ça va appeler une méthode, qui devra impérativement avoir une paramètre identifiant l'émetteur, parce qu'il est possible de lancer plusieurs requêtes réseau en même temps.


    Alors qu'avec la closure, son code est appelé directement. ça ajoute de la localité au code (ce n'est pas une méthode déléguée trois pages de code en dessous qui est appelée), et ne rend plus l'identification de l'émetteur nécessaire.


    Un autre avantage est celui de paramétriser le comportement. Par exemple, si tu as une fonction qui sert à  trier une liste, tu peux lui passer une closure qui décrit comment comparer deux objets.

    Voir par exemple la fonction sort() en Swift.

     



    les limites ?



    Parfois, la délégation est plus appropriée, parce qu'elle permet de décrire une plus grande variété de messages de retour.


  • Joanna CarterJoanna Carter Membre, Modérateur

    Petit exemple de l'utilisation d'un closure à  la place d'un delegate :



    protocol PropertyChangedDelegate
    {
    func propertyDidChange(sender: Any, propertyName: String)
    }

    struct DelegateObserver : PropertyChangedDelegate
    {
    func propertyDidChange(sender: Any, propertyName: String)
    {
    // réagir au changement
    }
    }

    struct DelegateSubject
    {
    var nom: String
    {
    didSet
    {
    delegate?.propertyDidChange(sender: self, propertyName: "nom")
    }
    }

    init(nom: String)
    {
    self.nom = nom
    }

    var delegate: PropertyChangedDelegate?
    }


    {
    let delegate = DelegateObserver()

    var delegateSubject = DelegateSubject(nom: "Swift")

    delegateSubject.delegate = delegate

    delegateSubject.nom = "Cocoa"
    }


    typealias PropertyChangeClosure = (Any, String) -> ()

    struct ClosureSubject
    {
    init(nom: String)
    {
    self.nom = nom
    }

    var nom: String
    {
    didSet
    {
    changeClosure?(self, "nom")
    }
    }

    var changeClosure: PropertyChangeClosure?
    }


    {
    var closureSubject = ClosureSubject(nom: "Swift")

    closureSubject.changeClosure =
    {
    (sender: Any, propertyName: String) in

    // réagir au changement
    }

    closureSubject.nom = "Cocoa"
    }
Connectez-vous ou Inscrivez-vous pour répondre.