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?

57
demandé sur icodebuster 2012-01-31 04:12:28

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:

Une liste des ivars internes sur un objet Obj-C lors de l'utilisation de l'opérateur de flèche

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

  1. (au moment de l'exécution) valeur de retour du champ

opérateur de flèche sur un objet C (pointeur)

  1. pointeur de déréférence
  2. valeur de retour du champ

opérateur de point / crochets sur un objet Objective-C (pointeur)

  1. (au moment de la compilation) remplacer par un appel à objc_msgSend
  2. (au moment de l'exécution) recherchez la définition de la classe Obj-C, lancez une exception si quelque chose a mal tourné
  3. pointeur de déréférence
  4. valeur de retour du champ

opérateur de flèche sur un objet Objective-C (pointeur)

  1. (au moment de l'exécution) pointeur de déréférence
  2. 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.

72
répondu darvids0n 2013-08-01 04:51:02

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).

9
répondu justin 2012-01-31 00:25:02

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];
6
répondu KomodoDave 2017-05-23 12:18:18

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.

2
répondu Chuck 2012-01-31 00:18:30

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.

1
répondu 5StringRyan 2012-01-31 00:22:00