En raison de la façon dont les objets Objective-C fonctionnent, const
cesse d'être une application et commence à être une notation pour le programmeur. Considérez ce programme:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Cela ne compilera pas ici (j'utilise clang): le compilateur peut détecter la tentative de modification du type C primitif et émet une erreur. Mais maintenant, comparez-le avec ce programme:
NSMutableString *f2(const NSMutableString * const x) {
[x appendString: @" world!"];
return x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
NSMutableString *x = [@"Hello" mutableCopy];
NSLog(@"%@", f2(x));
}
return 0;
}
Même si la fonction reçoit un pointeur constant vers un objet constant, il est toujours possible de muter l'objet.
Dans la programmation orientée objet, la meilleure façon de faire respecter la nature constante d'un objet est de rendre cet objet immuable - c'est-à-dire de ne fournir aucune méthode pouvant changer son état. Imaginez que la fonction ci-dessus prenne un NSString
argument au lieu de NSMutableString
, et que j'avais passé le littéral @"Hello"
au lieu d'une copie mutable. Il n'y a maintenant, raisonnablement, aucune chance de muter l'objet transmis [*]. Objective-C ne dispose d' aucun moyen de faire respecter que si, à la différence const
ou les final
références d'objets dans d' autres langues OO.
À titre de comparaison, const
fonctionne entièrement différemment en C ++. Si j'obtiens une const
référence à un objet C ++, je ne suis autorisé qu'à appeler des const
fonctions membres sur cet objet. Ces fonctions préservent l' const
état de l'objet, soit en n'apportant aucune modification, soit en modifiant uniquement les variables membres qui ont été explicitement marquées mutable
par le concepteur de classe. Imaginez donc que j'avais un type MutableString
en C ++ équivalent à NSMutableString
Objective-C. L'équivalent de mon exemple ci-dessus ressemblerait à quelque chose comme:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Cela ne compilera certainement pas: en plus de appendString()
ne pas être une const
opération, la fonction supprime le const
qualificatif de la référence de type qui nécessite un const_cast
.
[*] Je m'attends à ce qu'il y ait une manière déformée de le faire, mais maintenant nous sommes dans le royaume d'un programmeur essayant d'en saboter un autre en faisant des choses "intelligentes".