J'essaie de comprendre certaines des différences d'utilisation et de syntaxe en C par rapport à Objective-C. En particulier, je veux savoir comment (et pourquoi) l'utilisation diffère pour l'opérateur point et l'opérateur flèche en C par rapport à Objective-C. Voici un exemple simple.
Code C:
// declare a pointer to a Fraction
struct Fraction *frac;
...
// reference an 'instance' variable
int n = (*frac).numerator; // these two expressions
int n = frac->numerator; // are equivalent
Code Objective-C:
// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];
...
// reference an instance variable
int n = frac.numerator; // why isn't this (*frac).numerator or frac->numerator??
Donc, voyant comment frac
est le même dans les deux programmes (c'est-à-dire qu'il s'agit d'un pointeur vers un objet ou une structure Fraction), pourquoi utilisent-ils une syntaxe différente lors de l'accès aux propriétés? En particulier, en C, la propriété numerator
est accessible avec frac->numerator
, mais avec Objective-C, on y accède en utilisant l'opérateur point, avec frac.numerator
. Puisque frac
est un pointeur dans les deux programmes, pourquoi ces expressions sont-elles différentes? Quelqu'un peut-il m'aider à clarifier cela?
frac
n'est en fait pas le même dans les deux programmes.
Un C Fraction
est un struct
, qui est un type de base sans opérateur surchargé et qui ne peut être construit et détruit que par défaut. Si vous définissez des fonctions ou des champs sur la structure, la façon d'accéder à ces propriétés dans C
est avec l'opérateur point (.
). Objective-C conserve cet opérateur lorsque vous utilisez struct
s. Pour plus de commodité, vous pouvez effectuer une opération de déréférencement et de point à l'aide de l'opérateur flèche (->
) (Les deux expressions équivalentes que vous mentionnez). Objective-C conserve également cela lors de l'accès à struct
s.
Un Objective-C Fraction
dans votre exemple, cependant, est probablement (on pourrait supposer) un pointeur d'au moins type id
, qui est simplement un nom de classe et un pointeur vers l'instance de cette classe sous la hotte. Il est également très probable qu'il s'agisse d'une sous-classe de NSObject
ou NSProxy
. Ces classes Objective-C sont spéciales en ce qu'elles ont une couche entière d'opérations prédéfinies au-dessus d'une structure C
(si vous voulez vraiment y creuser, vous pouvez jeter un œil à la Référence d'exécution d'Objective-C ). Il est également important de noter qu'une classe Objective-C est toujours un pointeur .
L'une des opérations les plus élémentaires est objc_msgSend
. Lorsque nous opérons sur ces types d'objets, le compilateur Objective-C interprète un opérateur point (.
) Ou la syntaxe entre crochets ([object method]
) Comme un appel de méthode objc_msgSend
. Pour plus d'informations sur ce qui se passe réellement ici, voir cette série de messages par Bill Bumgarner, un ingénieur Apple qui supervise le développement du runtime Obj-C.
L'opérateur flèche (->
) N'est pas vraiment censé être utilisé sur les objets Objective-C. Comme je l'ai dit, les instances de classe Objective-C sont une structure C avec une couche de communication supplémentaire ajoutée, mais cette couche de communication est essentiellement contournée lorsque vous utilisez la flèche. Par exemple, si vous ouvrez Xcode et tapez [UIApplication sharedApplication]->
, Puis affichez la liste d'achèvement de la méthode, vous voyez ceci:
Ici vous pouvez voir un tas de champs normaux auxquels nous accédons généralement avec la syntaxe entre crochets (comme [[UIApplication sharedApplication] delegate]
). Ces éléments particuliers, cependant, sont les champs C
qui stockent les valeurs de leurs propriétés Objective-C respectives.
Donc, vous pouvez à peu près y penser comme ceci:
Opérateur de points sur un objet C
Opérateur fléché sur un objet C (pointeur)
Opérateur point/crochets sur un objet Objective-C (pointeur)
objc_msgSend
Opérateur de flèche sur un objet Objective-C (pointeur)
Maintenant, je simplifie certainement trop ici, mais pour résumer: les opérateurs de flèche semblent faire essentiellement la même chose dans les deux cas, mais l'opérateur de point a une signification supplémentaire/différente dans Objective-C.
La notation par points est un choix de conception. Puisque nous traitons toujours des pointeurs vers des instances objc, je suppose que les concepteurs voulaient quelque chose de familier, qui ne casserait pas non plus les programmes existants. Il a été introduit dans ObjC 2 - il y a quelques années à peine. Avant cela, vous deviez toujours utiliser des crochets pour la messagerie.
La notation par points fait une différence - ce n'est pas un accès direct, mais un message.
C'est:
obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;
val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;
Vous pouvez toujours écrire obj->ivar
pour accéder à un pointeur sur les membres de l'objet (s'il est visible).
Dans votre premier exemple, Fraction
est une structure. Dans votre deuxième exemple, Fraction
est une classe Objective-C (et dans iOS serait probablement une sous-classe de NSObject
).
C++ ne permet pas surcharge de operator .
. Par conséquent, sans informations supplémentaires, vous pouvez en déduire que la notation par points que vous voyez est une construction de langage supplémentaire intégrée à Objective-C, plutôt qu'un opérateur défini ou surchargé C/C++.
En l'occurrence, la notation par points est simplement une caractéristique de conception que les implémenteurs ont choisie comme raccourci pour l'accès à la propriété, entièrement équivalente au getter entre crochets:
myObjCVar.prop == [myObjCVar prop];
L'opérateur point sur les objets est une syntaxe spéciale pour accéder aux propriétés des objets. Il appelle le getter ou le setter de la propriété dans les coulisses. Ainsi, par exemple, [@"hello" length]
et @"hello".length
sont équivalents *. Pour tous les autres types, le point est le même que le point C et la flèche est toujours la même.
* Remarque: La méthode d'accesseur ne sera pas toujours nommée de la même manière que la propriété. S'il s'agit d'une propriété déclarée et que la déclaration désigne une méthode getter ou setter spéciale, celle-ci sera utilisée à la place.
La notation des points et des flèches est également la même en C que dans Objective-C (sur-ensemble strict de). Je pense que la différence fondamentale qui doit être distinguée est la différence entre une structure et un objet Objective-C.
La notation par points utilisée pour les objets dans Objective-C est utilisée pour les propriétés introduites dans Objective-C 2.0. Cependant, avec les structures, la notation -> et les points entre Objective-C et C sont les mêmes.