[swift] Invoquer une méthode avec un receiver donné
En swift, on peut référencer une méthode, c'est à dire une fonction liée à une classe ou struct particulière.
let set:Set = [1,2]
let fonction:(Set) -> Set = set.intersectSet
Ensuite, on n'a plus qu'à invoquer cette méthode avec les arguments ad hoc:
let result = fonction.([2,3] as Set) // -> {2}
Dans l'exemple précédent, j'ai référencé la méthode par le biais d'une instance. Quand on l'appelle, cette instance devient implicitement le receiver de la fonction. Ca parait logique.
Maintenant, il se trouve que l'on peut aussi référencer la méthode en passant par le type lui-même:
let methode: Set<Int> -> (Set) -> Set = Set.intersect
Sympa Swift. Juste un petit souci: comment invoquer cette méthode avec un receiver de mon choix ?
C'est l'équivalent de apply en javascript qu'il faudrait et je ne l'ai pas trouvé pour l'instant. Et d'ailleurs, si ce n'est pas possible, on peut se demander pourquoi on nous laisse référencer un objet dont on ne peut rien faire !
Réponses
Self-réponse:
On peut faire ça:
Je viens de relire le chapitre sur les fonctions du manuel Swift 2.1 et n'ai rien vu à ce sujet. Quelqu'un sait si cette façon d'appeler une méthode est documentée qque part ?
(C'est aussi dû au fait que Swift est un langage fonctionnel donc dans lequel les fonctions sont des first-class-citizen comme on dit, et peuvent être stockés dans des variables et passés en argument etc.)
Tu trouveras d'avantages d'exemples pratiques sur mon blog dans l'article Fun with Functions.
(Enfin là j'ai testé avec la sandbox IBM sous linux)
Il faudrait juste que le pointeur de fonction soit résolu au moment de l'appel car à ce moment là on connait le type de l'objet.
Enfin bon, j'imagine qu'ils ont dû y penser... et que ce n'est pas possible pour une bonne raison, c'est quand même décevant.
Et cela ferait une vraie différence par rapport aux vieux pointeurs de fonctions en C ou C++.
Si je ne me mélange pas les pinceaux, je pense que cela pourrait permettre de faire du binding sans avoir à forcer à l'avance les protocoles à utiliser.
Pour un binding qui consomme un int, il faut une variable qui contient une fonction qui renvoie un int et une variable qui contient un objet qui à priori implémente cette fonction.
En fait ça reviendrait à avoir un type de variable "fonction d'un protocole" qu'on pourrait utiliser sur un objet qui implémente le même protocole, sans avoir à connaà®tre à l'avance le protocole.
Le plus grosse fonctionnalité avancé en Swift 2 est le contraire de ce que tu dis . C'est une révolution les "protocol extension" dans Swift. On peut implanter des méthodes dans un protocol et permettre aux autres classes/structs qui se conforme a ce protocol d'avoir ce comportement gratuitement. la library standard Swift se base beaucoup sur ça : CollectionType, SequenceType,....
Problème :
Comme j'ai dit, c'est pas possible, il faut un struct ou classe qui implement le protocole pour accéder les membres du protocol.
Dans Xcode, cela fait planter le service playground, j'ai donc soumis un radar.
Je n'ai pas encore essayé dans le REPL Swift.
@AliGator
J'ai lu ton blog, qui est très instructif. Tu dis que tu prépare un article sur les Abstract Class (ou similaire) en swift. J'en salive d'avance parce que je suis en train de porter NSExpression en swift. C'est un cas intéressant parce qu'il y a plusieurs contraintes, et pas seulement le fait que init ne retourne rien en swift, qui rendent la chose assez sportive.