7
votes

Objective-C: Pourquoi les ivars privés ne sont pas cachés de l'accès extérieur lors de l'utilisation de KVC

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: xxx

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.

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" :)


2 commentaires

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.


5 Réponses :


4
votes

Ne déclarez pas un @property pour un ivar si vous voulez vraiment rester privé.

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 @property et @ synthétises 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.

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.

Si vous déclarez simplement un ivar comme @private 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é.



0
votes

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


4 commentaires

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.



10
votes

NsObject conforme à la NskeyValuecoding Protocole informel. Cela définit SetValue: Forey: et ValueForKey: . SETVALUE: FORKEKE: et ValueForKey: 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 , qui fait partie du protocole informel NskeyValuecoding, qui par défaut renvoie oui , 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.

Pour résoudre ce problème, vous devrez remplacer les méthodes mentionnées ci-dessus et définies dans le protocole informel NskeyValuecoding pour empêcher leur accès.

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.


3 commentaires

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.



3
votes

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


0 commentaires

1
votes

Je vais ajouter mes deux cents à cette ancienne question.

Je pense que le @private , @Protected est également là pour empêcher l'accès à une variable à l'aide de l'opérateur "->"

Imaginez Vous avez un ivar appelé myprivatevar déclaré comme ci-dessous: xxx

Donc, même si vous implémentez la méthode de classe ci-dessous pour retourner non et ne disposez pas des accesseurs déclarés pour l'ivar: xxx

La variable est toujours accessible si vous utilisez myClassobj-> myprivatvar < / forte>;

d'autre part si vous faites simplement le @public à @private et ne pas implémenter accessinstancevariabledrectly , la variable est toujours accessible à l'aide de KVC: xxx

(et non accessible via myClassObj-> myprivatevar )

Donc, pour rendre votre ivar complètement privé, il convient de déclarer que @private ainsi que AccessInstanceVariablesDirectement doit être implémenté pour renvoyer non . .


0 commentaires