Après avoir essayé d'accéder à des ivars à l'aide de KVC, j'ai remarqué qu'il n'y avait aucune protection sur des ivars privés et protégés. Peu importe ce que j'ai mis en avant le mot-clé Ivar (privé ou protégé) - un ivar est toujours un ivar public lors de l'utilisation de la méthode KVC "SETVALUE". Voici mon code dans lequel toutes les sept ivars et les sept propriétés sont changements à l'extérieur de l'instance de classe: résultat de la sortie> public_num = 1, protégé_num = 2, privé_num = 3, public_property = 3, 4, privé_property = 5, très_private_num = 6, très_private_property = 7. P> Même si l'ivar a déclaré à l'interface privée, il est toujours modifiable à l'extérieur de la classe. Alors, comment dois-je faire respecter l'encapsulation et "protéger mes iTARD de mauvais programmeurs d'autres programmes" :) p> p>
5 Réponses :
Ne déclarez pas un Ce n'est pas l'ivar qui n'est plus privé. L'exécution de l'objectif-C n'a pas de concept de méthodes privées. Étant donné que l'utilisation de Mais ce n'est pas aussi mauvais que vous le pensez. En utilisant les méthodes que vous avez ne changez pas directement l'ivar - il passe par les configurateurs. Si vous avez besoin d'une protection supplémentaire, vous pouvez écrire votre propre setter qui implémente la protection dont vous avez besoin. P>
Si vous déclarez simplement un ivar comme @property code> pour un ivar si vous voulez vraiment rester privé. P>
@property code> et @
synthétises code> génère des méthodes d'accesseur conformes à KVC, vous pouvez toujours appeler les méthodes, que l'ivar de soutien soit privé ou non. P>
@private code> et ne le faites pas KVC conformes - il restera privé. Bien sûr; Vous ne pouvez alors utiliser KVC ou KVO sur cette ivar, mais si vous vouliez pouvoir les utiliser, vous ne devriez pas la déclarer comme ivar privé. P>
Désolé pour le bazar. Je veux dire, je mets le seul ivar privé sans @property et @synthèse. Néanmoins, Ivar est accessible de l'extérieur à l'aide de SetValue de méthode KVC et la sortie de 11 est indiquée.
Ne le déclarez pas comme un @property code> pour un début. Ne pas implémenter les configurations et les getters pour cet ivar. Voici un guide rapide sur kvc a >
Je mets le code complet dans le premier commentaire sans @property et @synthesize. Et je n'ai pas implémenté Setter et Getter pour cet ivar. Pourtant, je peux y accéder avec SetValue. Alors où est l'astuce :)
ATTENTION: La réponse totalement erronée b>. Si hériter de NsObject, la classe est conforme au KVC. KVC accédera à la variable d'instance correspondante directement à la recherche d'aucune méthode d'accessoir pour une propriété Par défaut B>. Si ceci est pas b> ce que vous voulez, renvoyez NO dans + AccessInstanceVariablesDirectement code>
En outre, déclarez comme @private code> est inutile.
interdire via une substitution des entrées KVC:
@implementation MONObject - (id)valueForKey:(NSString *)key { /* enforce it */ return nil; } - (void)setValue:(id)value forKey:(NSString *)key { /* enforce it */ } /* and so on */ @end
Merci. IMHO, je conclurais que Obj-C n'a pas de véritable mécanisme privé. C'est une question de contournement de simuler la privatité souhaitable et de remplacer le comportement par défaut du compilateur (ou du temps d'exécution?). Mais alors, il est étrange pourquoi ces mots-clés comme "privés" et "protégés" sont utilisés dans la déclaration s'ils n'ont pas d'impact réel. Je pense qu'ils confondent les gens, en particulier les débutants.
IMHO, il s'agit de la compétence d'un programmeur de suivre des conventions de travail en utilisant des propriétés via des setters personnalisées ou synthétisées et des getters pour contrôler les valeurs des ivars / propriétés. IMHO, l'encapsulation n'est utilisée que comme convention de travail. Au fait, simulez-vous / utilisez des ivars / propriétés / méthodes privées dans vos projets réels?
Utilisez un ivar privé C ++ ou une classe privée où vous en avez besoin
J'écris plus C ++ que l'Objc - Je choisis la bonne langue pour la tâche.
NsObject conforme à la NskeyValuecoding Protocole informel. Cela définit Pour résoudre ce problème, vous devrez remplacer les méthodes mentionnées ci-dessus et définies dans le protocole informel code> NskeyValuecoding code> pour empêcher leur accès. P>
Comme mentionné par Abizern, les propriétés des variables privées sont toujours accessibles car l'objectif-c n'a pas de concept de méthodes privées. P> SetValue: Forey: code> et
ValueForKey: code>.
SETVALUE: FORKEKE: CODE> et
ValueForKey: CODE> Recherchez un moyen d'accéder à la valeur de la clé en fonction de Règles de recherche spécifiques qui inclut directement l'accès à la variable d'instance. Cet accès direct est contrôlé par
AccessInstanceVariablesDirectement code>, qui fait partie du protocole informel NskeyValuecoding, qui par défaut renvoie
oui code>, permettant à ces méthodes d'accéder directement aux variables d'instance et en tant que résultat ne les rend pas vraiment privés comme tels. Ils sont toujours privés de l'accès direct. P>
Merci. J'essaie toujours d'apprendre Obj-C, je pensais donc que KVC est la voie d'accès directe (en dehors de la classe) ...
Que pensez-vous, pourquoi ces mots-clés comme "privés" et "protégés" sont utilisés dans la déclaration d'interface s'ils n'ont pas d'impact réel? Ils confondent des gens, en particulier les débutants. De plus, pourquoi il est appelé "interface privée" qui réside dans le fichier de mise en œuvre s'il n'y a pas de véritable "privatité"?
Je travaille principalement avec Obj-C et C ++ et dans les deux langues, il existe des moyens de contourner les spécificateurs d'accès tels que privés et protégés. Vraiment, il s'agit d'un guide ou d'un indicateur aux développeurs utilisant cette classe qu'ils ne devraient pas toucher quoi que ce soit qui n'est pas marqué comme public. Bien que cet exemple soit une bibliothèque, il n'ya également aucune raison pour que quelqu'un utilise une bibliothèque qui a des en-têtes facilement modifiables ne peut pas simplement retirer @private de l'en-tête.
Aujourd'hui, j'ai remarqué une chose intéressante. Stephen Kochan, dans son livre "Programmation dans l'objectif C 2.0", indique un fait intéressant sur la relation Obj-C et C: "Lorsque vous définissez une nouvelle classe et ses variables d'instance, ces variables d'instance sont réellement stockées à l'intérieur d'une structure". Par conséquent, l'accès direct à un tel ivar pourrait être effectué en utilisant -> opérateur. Donc, final, j'ai trouvé où de tels mots clés que @private et @Protection sont vraiment importatent vraiment. Si j'essaie directement de modifier la valeur de l'ivar public dans le programme principal en utilisant, tout va bien - la valeur sera modifiée. Mais si j'essaie de changer de ivar privé - alors le compilateur me mettra en garde sur privé_num étant un ivar privé
myClass->public_num = [NSNumber numberWithInt:11]; myClass->private_num = [NSNumber numberWithInt:11]; // compiler will complain and reject the compilation
Je vais ajouter mes deux cents à cette ancienne question.
Je pense que le Imaginez Vous avez un ivar appelé Donc, même si vous implémentez la méthode de classe ci-dessous pour retourner La variable est toujours accessible si vous utilisez d'autre part si vous faites simplement le (et non accessible via Donc, pour rendre votre ivar complètement privé, il convient de déclarer que @private code>,
@Protected code> est également là pour empêcher l'accès à une variable à l'aide de l'opérateur "->" p>
myprivatevar code> déclaré comme ci-dessous: p>
non code > et ne disposez pas des accesseurs déclarés pour l'ivar: p>
myClassobj-> myprivatvar code> < / forte>; p>
@public code> à
@private code> et ne pas implémenter
accessinstancevariabledrectly Code>, la variable est toujours accessible à l'aide de KVC: p>
myClassObj-> myprivatevar code>) p>
@private code> ainsi que
AccessInstanceVariablesDirectement code> doit être implémenté pour renvoyer
non code>. P>. p>
Jusqu'à présent, j'ai remarqué que la seule façon d'avoir "une sorte de méthode privée" est de déclarer une méthode pure dans une interface privée (sans utiliser de synthétisation). Ensuite, le compilateur met en garde sur la méthode introuvable. Mais le code fixe et la méthode est exécutable :). J'ai écrit nslog (@ "à l'intérieur de Hiddenmethod \ n") dans le Hiddenmethod, puis exécuté cette méthode à partir du principal et j'ai eu le message dans la fenêtre de débogage. }
Il n'y a pas de méthodes privées dans l'objectif-c.