Debido a la forma en que funcionan los objetos Objective-C, const
deja de ser una aplicación y comienza a ser una notación para el programador. Considere este programa:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Eso realmente no se compilará aquí (estoy usando clang): el compilador puede detectar el intento de modificar el tipo C primitivo y emite un error. Pero ahora compáralo con este programa:
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;
}
Aunque la función pasa un puntero constante a un objeto constante, aún es posible mutar el objeto.
En la programación orientada a objetos, la mejor manera de hacer cumplir la naturaleza constante de un objeto es hacer que ese objeto sea inmutable, es decir, no proporcione ningún método que pueda cambiar su estado. Imagina que la función anterior tomó un NSString
argumento en lugar de NSMutableString
, y que pasé el literal en @"Hello"
lugar de una copia mutable. Ahora, razonablemente hablando, no hay posibilidad de mutar el objeto pasado [*]. Objective-C no tiene ninguna manera de hacer cumplir eso, aunque, a diferencia de const
o final
referencias a objetos en otros lenguajes orientados a objetos.
A modo de comparación, const
funciona de manera completamente diferente en C ++. Si obtengo una const
referencia a un objeto C ++, solo se me permite llamar a const
funciones miembro en ese objeto. Estas funciones preservan la const
naturaleza del objeto, ya sea al no hacer ningún cambio o al modificar solo las variables miembro que han sido marcadas explícitamente mutable
por el diseñador de la clase. Así que imagina que tengo algún tipo MutableString
en C ++ que es equivalente a NSMutableString
en Objective-C. El equivalente de mi ejemplo anterior se vería así:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Esto definitivamente no se compilará: además de appendString()
no ser una const
operación, la función elimina el const
calificador de la referencia de tipo que requiere a const_cast
.
[*] Espero que haya una forma retorcida de hacerlo, pero ahora estamos en el ámbito de un programador que intenta sabotear a otro haciendo cosas "inteligentes".