Dot (".") opérateur et flèche ( "- > " ) utilisation de l'opérateur en C VS objectif-C
J'essaie de comprendre certaines des différences d'utilisation et de syntaxe dans C vs. Objective-C. En particulier, je veux savoir comment (et pourquoi) l'utilisation diffère pour l'opérateur dot et l'opérateur arrow dans C vs. 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 Objectif-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, vu comment frac
est le même dans les deux programmes (c'est-à-dire qu'il s'agit d'un pointeur vers un objet Fraction ou une structure), pourquoi utilisent-ils différents syntaxe 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, elle est accessible en utilisant l'opérateur dot, avec frac.numerator
. Depuis frac
est un pointeur dans les deux programmes, pourquoi ces expressions sont-elles différentes? Quelqu'un peut-il aider à clarifier cela pour moi?
5 réponses
frac
est en fait pas la même chose dans les deux programmes.
Un C Fraction
est un struct
, qui est un type de base sans opérateurs surchargés et qui ne peut vraiment être construit et détruit que par défaut. Si vous définissez des fonctions ou des champs sur la structure, la manière d'accéder à ces propriétés dans C
est le point (.
) de l'opérateur. 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érence et de point en utilisant l'opérateur arrow (->
) (le deux expressions équivalentes que vous mentionnez). Objective-C préserve également cela lors de l'accès à struct
S.
Un Objective-C Fraction
dans votre exemple, cependant, est probablement (on supposerait) un pointeur d'au moins type id
, qui est simplement un nom de classe et un pointeur vers l'instance de cette classe sous le capot. Il est également très probable que ce soit une sous-classe de NSObject
ou NSProxy
. Ces classes Objective-C sont spéciales en ce sens qu'elles ont toute une couche d'opérations prédéfinies au-dessus d'une structure C
(si vous voulez vraiment creuser dedans alors vous pouvez jeter un oeil à la référence D'exécution 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 dot (.
) ou la syntaxe des 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 de L'Obj-C runtime.
L'opérateur arrow (->
) 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 supplémentaire de communication 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 ce:
Ici vous pouvez voir un tas de champs normaux auxquels nous accédons généralement avec une syntaxe entre crochets (comme [[UIApplication sharedApplication] delegate]
). Cependant, ces éléments particuliers sont les champs C
qui stockent les valeurs de leurs propriétés objectives-C.
Donc, vous pouvez à peu près penser comme ceci:
l'opérateur de Point sur un objet C
- (au moment de l'exécution) valeur de retour du champ
opérateur de flèche sur un objet C (pointeur)
- pointeur de déréférence
- valeur de retour du champ
opérateur de point / crochets sur un objet Objective-C (pointeur)
- (au moment de la compilation) remplacer par un appel à
objc_msgSend
- (au moment de l'exécution) recherchez la définition de la classe Obj-C, lancez une exception si quelque chose a mal tourné
- pointeur de déréférence
- valeur de retour du champ
opérateur de flèche sur un objet Objective-C (pointeur)
- (au moment de l'exécution) pointeur de déréférence
- valeur de retour du champ
Maintenant, je simplifie définitivement ici, mais pour résumer: les opérateurs de flèche semblent faire fondamentalement 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. 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-à-dire:
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 vers membres de l'objet (si 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 de surcharge de operator .
. Par conséquent, sans informations supplémentaires, vous pouvez déduire que la notation par points que vous voyez est une construction de langage supplémentaire intégrée dans Objective-C, plutôt qu'un opérateur c/c++ défini ou surchargé.
Comme il arrive, la notation de point est simplement une caractéristique de conception le les implémenteurs ont choisi comme raccourci pour l'accès à la propriété, entièrement équivalent 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 getter ou 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 le même.
* Remarque: La méthode 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 plutôt.
La notation des points et des flèches est également la même en C qu'en Objective-C (surensemble 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 dot entre Objective-C et C sont les mêmes.