2012-08-23 7 views
0

J'ai remarqué à partir du code source LLVM que le compilateur prend en charge le drapeau:Objective C chaîne constante conversion implicite?

-fconstant-string-class=CLASSNAME 

Si ce drapeau est pas présent, le compilateur semble par défaut NSConstantString.

Lors de l'inspection de la bibliothèque Foundation d'Apple, NSConstantString hérite de NSSimpleCString qui fournit les ivars requis pour activer le comportement de chaîne constante ObjC. Ceci est à son tour une classe enfant de NSString.

Cependant, en code normal ObjC, ce qui suit est parfaitement légal:

NSString *anNSString = @"This is an NSConstantString?"; 

Cela semble bien (NSConstantString est la classe enfant), à l'exception:

1) Les données d'une constante chaîne devrait être canalisé dans les ivars déclarés dans NSSimpleCString, qui ne sont pas disponibles pour un NSString.

2) Les méthodes d'itération de NSString suggèrent qu'il est construit sur des tableaux d'unichars. Cela signifie qu'il doit y avoir une conversion des caractères de NSConstantString vers les unichars de NSString.

Comme la surcharge de l'opérateur n'est pas possible dans Objective C, comment/où cette conversion a-t-elle eu lieu? Y a-t-il des trucs de génération de codes qui se passent ici? Ou ai-je manqué quelque chose de plus évident?

Répondre

3

Ce n'est pas le seul endroit dans le cadre que vous trouverez que la classe que vous traitez n'est pas la classe que vous attendez. Comme Objective-C est dactylographié, il n'a même pas besoin d'être une relation d'héritage entre les classes (bien que ce soit souhaitable de laisser isKindOfClass: fonctionner correctement).

La pratique consistant à utiliser une "classe avant" en tant qu'interface et un groupe de "classes privées" pour l'implémentation est élevée à un modèle dans le framework Cocoa. Ce concept est appelé "cluster de classe" et la plupart des classes Foundation ont leur propre cluster. Comme ils partagent tous la même interface publique, tout fonctionne comme vous l'attendez. En ce qui les concerne, les classes antérieures elles-mêmes devraient probablement être considérées comme abstraites (même si le concept de compilation d'une classe abstraite n'existe pas en Objective-C).

Par exemple, NSArray et NSMutableArray deviennent NSCFArray une fois que vous avez appuyé sur le bouton Exécuter. Un autre cas de frappe flagrante de canard: la dernière fois que j'ai vérifié, quand vous appelez une méthode qui traite des chemins sur un NSString (par exemple stringByAppendingPathComponent:), vous obtenez une instance de la classe NSPathStore2, même si la documentation indique qu'elle renvoie un NSString.

Je ne vois pas comment les ivars de NSConstantString pourraient avoir de l'importance à NSString tant que toutes les méthodes pertinentes sont implémentées/remplacées dans NSConstantString. En ce qui concerne la conversion elle-même, il n'y a pas beaucoup de points d'accès publics à unichar s: à mon avis, seulement 5 NSString méthodes utilisent unichar s, donc toute conversion nécessaire pourrait facilement être faite là.

EDIT je suis allé un peu plus loin et a découvert NSString déclare pas Ivar, ce qui laisse une discrétion absolue à ses sous-classes dans la mesure où le stockage est concerné. NSSimpleCString déclare char* bytes et int numBytes; NSConstantString n'ajoute pas d'ivar. Les deux classes implémentent/remplacent les méthodes d'accès unichar.

+0

Bonne réponse. Pour clarifier un peu: 'NSString' ne se soucie pas de ses ivars, même en interne ... toute sa fonctionnalité passe par les méthodes primitives' longueur' et 'characterAtIndex:'. Tant que son propre code et toutes les autres classes qui l'utilisent respectent ce contrat, 'NSConstantString' peut implémenter ces méthodes comme bon lui semble et toujours interopérer. – rickster

+0

vous pouvez ressentir un certain inconfort et/ou désorientation au début, mais cela va passer dans le temps. :) – nielsbot

+0

Merci beaucoup :). En ce qui concerne votre édition - comment avez-vous pu constater que NSString ne déclare pas d'ivars supplémentaires? Pour être en mesure d'obtenir ce type d'informations internes pour d'autres classes serait plutôt utile ..! – Ephemera

1

Objective-C est un langage de répartition dynamique. Vous déclarez la variable comme NSString*, mais il pourrait en fait être une sous-classe de NSString*. Puisque toutes les méthodes sont distribuées de manière dynamique (par exemple invocation de méthode), peu importe ce que le compilateur pense du type de l'objet [1], il importe seulement ce que l'objet est en réalité. Donc, dans cette ligne de code, votre variable anNSString contient effectivement un NSConstantString au lieu d'un NSString.

[1]: le type affecte le processus de recherche du sélecteur, qui affecte ce que le compilateur pense que les types d'arguments devraient être, ce qui affecte les avertissements potentiels et la coercition implicite des types. Rien de tout cela n'est pertinent ici.

Questions connexes