Le comportement est extrêmement similaire à la Array.Resize
méthode dans .NET. Pour comprendre ce qui se passe, il peut être utile de consulter l'historique du .
jeton en C, C ++, Java, C # et Swift.
En C, une structure n'est rien de plus qu'une agrégation de variables. L'application de la .
à une variable de type structure permet d'accéder à une variable stockée dans la structure. Les pointeurs vers les objets ne contiennent pas d' agrégations de variables, mais les identifient . Si l'on a un pointeur qui identifie une structure, l' ->
opérateur peut être utilisé pour accéder à une variable stockée dans la structure identifiée par le pointeur.
En C ++, les structures et les classes agrégent non seulement les variables, mais peuvent également y attacher du code. Utiliser .
pour invoquer une méthode demandera à une variable d'agir sur le contenu de la variable elle-même ; l'utilisation ->
d'une variable qui identifie un objet demandera à cette méthode d'agir sur l'objet identifié par la variable.
En Java, tous les types de variables personnalisées identifient simplement les objets, et l'invocation d'une méthode sur une variable indiquera à la méthode quel objet est identifié par la variable. Les variables ne peuvent pas contenir directement tout type de type de données composites, ni aucun moyen permettant à une méthode d'accéder à une variable sur laquelle elle est invoquée. Ces restrictions, bien que sémantiquement limitantes, simplifient considérablement l'exécution et facilitent la validation du bytecode; de telles simplifications ont réduit les frais généraux de Java à un moment où le marché était sensible à de tels problèmes, et l'ont ainsi aidé à gagner du terrain sur le marché. Ils signifiaient également qu'il n'y avait pas besoin d'un jeton équivalent à celui .
utilisé en C ou C ++. Bien que Java aurait pu utiliser ->
de la même manière que C et C ++, les créateurs ont choisi d'utiliser un seul caractère.
car il n'était pas nécessaire à d'autres fins.
En C # et dans d'autres langages .NET, les variables peuvent soit identifier des objets, soit contenir directement des types de données composites. Lorsqu'il est utilisé sur une variable d'un type de données composite, .
agit sur le contenu de la variable; lorsqu'il est utilisé sur une variable de type référence, .
agit sur l'objet identifiépar cela. Pour certains types d'opérations, la distinction sémantique n'est pas particulièrement importante, mais pour d'autres, elle l'est. Les situations les plus problématiques sont celles dans lesquelles une méthode d'un type de données composite qui modifierait la variable sur laquelle elle est invoquée, est invoquée sur une variable en lecture seule. Si une tentative est faite pour appeler une méthode sur une valeur ou une variable en lecture seule, les compilateurs copient généralement la variable, laissent la méthode agir en conséquence et ignorent la variable. Ceci est généralement sûr avec des méthodes qui ne lisent que la variable, mais pas avec des méthodes qui y écrivent. Malheureusement, .does n'a pas encore de moyen d'indiquer quelles méthodes peuvent être utilisées en toute sécurité avec une telle substitution et lesquelles ne le peuvent pas.
Dans Swift, les méthodes sur les agrégats peuvent indiquer expressément si elles modifieront la variable sur laquelle elles sont invoquées, et le compilateur interdira l'utilisation de méthodes de mutation sur des variables en lecture seule (plutôt que de les faire muter des copies temporaires de la variable qui sera ensuite se débarrasser). En raison de cette distinction, l'utilisation du .
jeton pour appeler des méthodes qui modifient les variables sur lesquelles elles sont appelées est beaucoup plus sûre dans Swift que dans .NET. Malheureusement, le fait que le même .
jeton soit utilisé à cette fin pour agir sur un objet externe identifié par une variable signifie qu'il existe un risque de confusion.
Si nous avions une machine à remonter le temps et que nous revenions à la création de C # et / ou Swift, on pourrait éviter rétroactivement une grande partie de la confusion entourant ces problèmes en faisant en sorte que les langages utilisent les jetons .
et ->
d'une manière beaucoup plus proche de l'utilisation de C ++. Les méthodes des agrégats et des types de référence pourraient être utilisées .
pour agir sur la variable sur laquelle ils ont été invoqués et ->
pour agir sur une valeur (pour les composites) ou sur la chose identifiée (pour les types de référence). Cependant, aucune des deux langues n'est conçue de cette façon.
En C #, la pratique normale pour une méthode de modifier une variable sur laquelle elle est invoquée est de passer la variable comme ref
paramètre à une méthode. Ainsi, l'appel Array.Resize(ref someArray, 23);
lors de l' someArray
identification d'un tableau de 20 éléments entraînera l' someArray
identification d'un nouveau tableau de 23 éléments, sans affecter le tableau d'origine. L'utilisation de ref
indique clairement que la méthode doit être censée modifier la variable sur laquelle elle est invoquée. Dans de nombreux cas, il est avantageux de pouvoir modifier des variables sans avoir à utiliser des méthodes statiques; Swift résout cela en utilisant la .
syntaxe. L'inconvénient est qu'il perd de préciser quelles méthodes agissent sur les variables et quelles méthodes agissent sur les valeurs.