Les Optionnelles
Gercofis
Membre
J'ai beaucoup de mal a en comprendre le fonctionnement et l'utilité...
Donc un discussion sur ce sujet sera peut-être utile a beaucoup ?
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Ce qui me semble un peu plus compliqué, c'est après: soit on a déterminé qu'une valeur a bien été renvoyée, auquel cas on peut écrire variable! pour forcer son utilisation, soit on se trimbale cette incertitude dans la suite du code.
Je dirais, relis la doc. La notion me semble un peu compliquée, mais c'est bien expliqué.
Il est dit dans la doc :
Et on a comme exemple :
En gros c'est ce qu'a dit Céroce. Une variable optionnelle n'est pas "certaine" d'avoir une valeur. Et si avec ce code tu changes optionnaleName en nil :
Et bien tu n'as aucune erreur qui apparait et greeting aura comme valeur "Hello John Doe".
La seule façon en ObjC c'est de retourner un nombre un peu spécial tellement grand qu'il est improbable. Il s'agit de NSNotFound, qui est une constante ayant pour valeur le plus grant Int possible. ça fait un peu bidouille quand même tu ne trouves pas ?
En ObjC pour les "objets qui n'existent pas" on a le mot clé `nilË‹... mais quand ce ne sont pas des objets qu'on manipule mais des Int, des Double... on n'a rien d'équivalent.
En Swift, on peut utiliser `nil` pour tous les types, que ce soit des Objets (instances de classes) ou des struct ou des Int ou Double ou même des enums.
Par contre la différence c'est qu'en Swift on peut marquer tout type comme étant optional (avec le "?" derrière le type de la variable) et pouvant être nil, mais aussi seuls les types marqués optional peuvent être nil.
Ainsi une 'var str: String' ne peut pas valoir nil (alors qu'une "NSString *str" peut, elle). Si tu veux indiquer que ta String peut potentiellement valoir nil il faut l'indiquer explicitement en lui donnant un type optional.
Cela permet d'avoir des fonctions par exemple qui prennent en paramètre des String qui sont garanties d'être non-nill, ou des fonctions qui retournent une String qui est garanti d'être non-nil, tant que tu ne définis c'est paramètres qu'avec le type "String" et pas "String?".
Au moins avec Swift :
1) On sait explicitement quand une fonction peut retourner nil ou pas, peut prendre des arguments nil ou doit absolument prendre des arguments non-nil
3) tous les types peuvent être marqués Optional et peuvent ainsi être nil... même les Int et les Struct (et pas que les NSObject comme en ObjC)
Oui, les types marqués Optional (?) peuvent être nil, donc là , dans cet exemple de la WWDC (session 402), on voit bien que la variable devient nil suite au retour appellé sur uné clé invalide d'un dico.
Par contre, en vérifiant dans le PlayGround, non seulement le caractère "?" autorise la valeur nil, mais ça la définit par défaut.
Ainsi:
me renvoie nil.
Si jamais on veut une valeur nil par défaut, pas la peine d'écrire:
Moi c'est
qui m'a un peu surpris quand j'ai lu cette section. Je m'attendais à une comparaison avec nil, comme on ferait dans biens des langages.
Est équivalent à : Donc "if let x = y" à la fois teste si y est nil, et s'il n'est pas nil l'affecte à x et exécute la boucle. Comme souvent quand tu testes si un optional est nil ou pas, c'est pour utiliser ensuite sa valeur dans le corps de la boucle, la syntaxe "if let" est assez pratique et fait du deux en un.
Mais si tu ne veux QUE tester si l'optional est nil ou pas, tu peux juste faire "if optionalName" qui vaudra vrai si optionalName a une valeur et faux s'il est nil.
Autant j'ai tout de suite compris l'intérêt des optionnals et leur puissance autant je ne comprends pas ceux qui sont implicitly unwarped.
J'ai vu dans les ref d'API que certaines fonctions/méthodes renvoyaient du String! (par exemple) ça veut dire quoi ? Qu'on a un optionnel unwarpé d'office ? Pourquoi dans ce ca ?
J'ai un peu du mal si quelqu'un pouvait éclairer ma lanterne ça serait sympa
En résumé, c'est pour déclarer un optional mais qu'on utiliserait comme s'il ne l'était pas. Comme si on déclarait une "var variable: Type?" mais qu'on utilisait toujours "variable!" au lieu de "variable" dans le reste du code pour forcer l'optional à être unwrappé (evidemment si l'optional est nil, cela va planter au runtime)
Leur intérêt est forcément moins clair, mais en gros c'est pratique :
1. Cas de références croisées et de valeurs nil "que pendant l'init"
Dans des cas où on a des références croisées entre classes, par exemple une classe Person qui aurait une propriété "creditCard: Card" et une classe "Card" qui aurait une propriété "owner: Person". Si on considère dans notre modèle que une Person a toujours carte de crédit et qu'une carte de crédit a toujours un propriétaire, on a une référence croisée. Dans ce cas :
Dans ce cas d'usage (expliqué en détail dans la vidéo... 403 il me semble, ou peut-être 404, où ils causent des strong reference cycles et de comment les éviter), un "implicitly unwrapped optional" est pratique car il n'y a que pendant la courte phase d'initialisation qu'on a besoin que ce soit un optional, mais ensuite on veut l'utiliser comme un type non-optional.
---
2. Lors du Bridging ObjC
Dans le cas du bridging de code Objective-C en Swift, les NSString sont traduites en objets String!. Les NSString sont potentiellement à nil, donc ça ne peut pas être juste des "String" non optionnelles, mais forcément au minimum des "String?". Mais en même temps, pour pouvoir utiliser la syntaxe exactement comme on utiliserait la même syntaxe en ObjC (où on appelle les méthodes directement sur l'objet sans avoir à l'unwrapper à chaque appel), ces APIs retournent plutôt des "String!", donc des String qui sont optional, mais qu'on utilise comme si ça n'en était pas.
Bien sûr, si on les utilise alors qu'elles sont nil, ça va planter, alors qu'en ObjC ça ignorait silencieusement l'appel (un appel de méthode sur nil ne fait rien en ObjC). Mais le fait que "String!" soit implicitly unwrapped n'empêche pas de pouvoir tester si l'optional a une valeur ("if implOptString { ... }")
Je te le concède, c'est un concept un peu plus difficile à appréhender. C'est clairement beaucoup moins fréquent d'avoir à déclarer des implicitly-unwrapped-optional dans notre code que des Optionals classiques. Mais pour tout ce qui est code bridgé, c'est sûr que tu vas en rencontrer pas mal. Faut voir ça comme "un type est est optional, mais qu'on utilise à l'appel comme s'il ne l'était pas" ou plutôt "qu'on utilise lors des appels comme si on unwrappait systématiquement sa valeur".
Mettre un "!" lors de la déclaration ça évite de devoir mettre des "!" ensuite un peu partout dans tous les appels où l'on utilise la variable/propriété. C'est discutable (ça enlève un peu de safety) mais c'est pratique surtout pour le bridging ou le cas 1 évoqué dans la vidéo.
Merci pour la réponse, c'est encore plus complexe que ce que j'imaginais.
Je vais revoir la vidéo pour essayer de vraiment saisir le truc.