Devido à maneira como os objetos Objective-C funcionam, const
deixa de ser uma aplicação e passa a ser uma notação para o 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;
}
Na verdade, isso não será compilado aqui (estou usando o clang): o compilador pode detectar a tentativa de modificar o tipo C primitivo e emitir um erro. Mas agora compare-o com 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;
}
Mesmo que a função passe um ponteiro constante para um objeto constante, ainda é possível alterar o objeto.
Na programação orientada a objetos, a melhor maneira de impor a natureza constante de um objeto é tornar esse objeto imutável - ou seja, não forneça nenhum método que possa alterar seu estado. Imagine que a função acima pegou um NSString
argumento em vez de NSMutableString
, e que eu havia passado a literal em @"Hello"
vez de uma cópia mutável. Agora, razoavelmente falando, não há chance de alterar o objeto passado [*]. Objective-C não tem qualquer maneira de impor que, embora, ao contrário const
ou final
referências de objeto em outras linguagens OO.
Para comparação, const
funciona de maneira totalmente diferente em C ++. Se eu receber uma const
referência a um objeto C ++, só posso chamar const
funções de membro nesse objeto. Essas funções preservam a const
integridade do objeto, não fazendo alterações ou modificando apenas variáveis de membros que foram explicitamente marcadas mutable
pelo designer de classe. Imagine que eu tivesse algum tipo MutableString
em C ++ equivalente a NSMutableString
Objective-C. O equivalente do meu exemplo acima seria algo como:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Definitivamente, isso não será compilado: além de appendString()
não ser uma const
operação, a função remove o const
qualificador da referência de tipo que requer a const_cast
.
[*] Espero que exista alguma maneira distorcida de fazê-lo, mas agora estamos no reino de um programador tentando sabotar outro fazendo coisas "inteligentes".