Key-Value Coding : Danger ?
segaouf
Membre
Bonjour a tous,
Je continue dans mon apprentissage du developpment cocoa. Hier soir j'ai appris l'existance du KVC. Mais ce concept est flippant, non ?
Il me semble que les variables d'instances sont prives par defaut dans objective-c, pas sur, mais si c'est vrai je trouve cela bien.
Par contre, avec KVC, on fait sauter cette protection, non ?
Ce qui me bloque, c'est qu'il me semble qu'avec le KVC on peut recuperer les variables d'un objet et les modifier, meme si le createur de la classe voulait nous forcer a passer par un setter ?
C'est pas dangereux ? Quel en est l'interet ?
Merci
Je continue dans mon apprentissage du developpment cocoa. Hier soir j'ai appris l'existance du KVC. Mais ce concept est flippant, non ?
Il me semble que les variables d'instances sont prives par defaut dans objective-c, pas sur, mais si c'est vrai je trouve cela bien.
Par contre, avec KVC, on fait sauter cette protection, non ?
Ce qui me bloque, c'est qu'il me semble qu'avec le KVC on peut recuperer les variables d'un objet et les modifier, meme si le createur de la classe voulait nous forcer a passer par un setter ?
C'est pas dangereux ? Quel en est l'interet ?
Merci
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Mais de toute façon le KVC passe par les setters et les getters s'ils existent. Donc si le concepteur de la classe a prévu un getter et un setter, ils seront utilisés quand tu utilises le KVC (ce qui permet de s'assurer du respect des règles de gestion mémoire retain/release, entre autres, quand tu utilises les setters).
Donc [tt][obj setValue:x forKeyPath:@a.b][/tt] sera équivalent à [tt][[obj valueForKey:@a] setValue:x forKey:@B][/tt] qui sera traduit par [tt][[obj a] setB:x][/tt], donc le setter setB sera bien appelé pour modifier la valeur de b.
Pour ce qui est de l'accès aux variables privées, il y a une protection. En effet, si tu regardes bien ce qui est indiqué ici dans la doc, tu verras que le KVC n'utilise en fait que les setters/getters (il faut donc qu'ils existent), et ne s'autorise à accéder directement aux variables (s'il ne trouve pas de setter/getter) que si [tt]accessInstanceVariablesDirectly[/tt] retourne YES.
Bon malheureusement (quoique ça se discute justement, ça a ses avantages, mais comporte aussi les risques que tu as soulevé concernant les variables privées du coup), l'implémentation par défaut de cette méthode (du protocole <NSKeyValueCoding>) retourne justement YES. Mais il suffit de la surcharger dans tes classes pour lui faire retourner NO et protéger ainsi tes variables privées y compris à l'égard du KVC.
Tres interessant (Comme d'hab de ta part quoi.)
J'etais plus au moins vaguement au courant pour la accessInstanceVariablesDirectly, j'avais lu ceci quelque part sur stackoverflow. Mais le fait qu'elle retourne YES par defaut la rend un peu inutile ...
J'ai aussi plus ou moins compris qu'il cherche le setter/getter en premier lieu. Mais Imaginons que je ne veux pas qu'il soit possible de setter une variable, je vais devoir creer un setter qui ne fait rien ! Tres mauvaise pratique, et cela peut rendre un developpeur completement maso en pensant que le setter est un vrai setter ...
Ou overrider accessInstanceVariablesDirectly ... Mais dans ce cas, on perd la finesse du public/privee, vu que toutes les variables dans cette classe deviendront accessible/inaccessible, non ?
La bonne pratique veut qu'on utilise tous des getters/setters. Si tu veux une variable read-only, elle aura un getter mais pas de setter.
C'est ce qui se passe quand tu déclares @property(readonly) d'ailleurs, ça ne déclare que le getter (et le @synthesize n'implémente donc que le getter aussi), c'est ce qui rend la propriété readonly.
Je n'ai jamais fait usage des @private et @public en Objective-C pour ma part :
Donc au final tu fais tout avec des @property (c'est fait pour ça de toute façon) et tu gardes toutes tes v.i. privées. Donc la seule chose que tu as à faire si tu ne veux pas que le KVC te foute la zone en risquant de modifier des variables auxquelles il ne devrait pas avoir accès, c'est de surcharger accessInstanceVariablesDirectly pour retourner NO.
En effet dommage que ça soit pas la valeur par défaut. Je ne vais pas rentrer dans des considérations subtiles de conception, il y a certains cas où justement ça peut être pratique (pour mimiquer le paradigme de "friend class" en Obj-C par exemple), mais c'est vrai que ça reste assez rare, donc l'inverse (retourner NO par défaut, et surcharger quand on veut bypasser ça justement pour des cas subtils où c'est utile) aurait été préférable de la part d'Apple mais bon.
Et en l'occurrence, la notion de variables/méthodes protégées/privées n'apporte aucune protection en réalité en C++, car il suffit de changer dans un ".h" C++ les mots clés "private:" par "public:" pour contourner la protection, et ce même si on ne dispose pas du code source complet des classes (il n'y a rien dans les fichiers ".o" générés à partir de source C++ qui permettent de forcer la visibilité des variables/méthodes). Tant que l'ordre des méthodes et des variables d'instance n'est pas changé, le .h restera compatible avec le code compilé.
Donc oui, KVC n'est pas forcément très sûr, mais C++ ne l'est absolument pas plus. Seuls les langages n'ayant pas de notion de fichier de déclaration (C#, Java, entre autre) sont suffisamment solides pour assurer que les niveaux de visibilité seront respectés et incontournables (et encore...).
Moi je viens de java, et c'est clair que j'ai rarement vu des variables en public avec un raisonnement qui se tenais derrière. La seule chose que je trouve dommage en java sur le public / protected / privée c'est le fonctionnement du protected : j'aurais aimé qu'il permette uniquement à une sous-classe d'avoir accès à la méthode varibale, mais il donne accès à tout le package ... Mais bon, qui suis-je pour critiquer .
Zoc, je n'ai jamais pratiqué C++ et je ne le ferais jamais, ma question n'était pas du tout dans le sens "bouuhhh regarder objective-c c'est de la m***!" j'adore objective-c ! D'ailleurs, j'y pense tout les jours au boulot quand je code en java . J'aimerais bien un job en développement Mac mais c'est pas à HSBC que je vais le trouver ^^.
Merci pour vos réponses, c'est vraiment bizarre ce KVC ... Il va falloir faire attention pour mon super projet de-la-mort-qui-tue-qui-va-me-rendre-riche-pour-acheter-pleins-dipad.
protected pas private !
Dans mes messages j'utilise le mot "privé" par opposition au mot "public", mais en effet j'aurais dû utiliser le terme "protected" pour le différencier du cas "@private"
Les sous-classes ont bien accès aux v.i. des classes parentes en ObjC.
D'ailleurs j'ai pas souvenir d'avoir vu un cas (même dans d'autres langages " vu qu'en Obj-C je n'ai pas ce pb de concepts pour ma part comme je le disais) où il y avait un intérêt à utiliser des variables vraiment privées (et non juste protected) ?
Access Levels -JAVA
ModifierClassPackageSubclassWorld
publicYYYY
protectedYYYN
no modifierYYNN
privateYNNN
Ce que j'aurais aimé ,c'est que protected agisse comme cela :
ModifierClassPackageSubclassWorld
protectedYNYN !
Le "protected" de Java permet à des classes d'un même package de "communiquer" entre elles tout en s'assurant que les variables/méthodes ne pourront pas être utilisées à l'extérieur du package. Pratique quand on développe des packages complexes réutilisables (API par exemple).