A causa del modo in cui gli oggetti Objective-C funzionano, const
rinuncia all'applicazione e inizia a essere una notazione per il programmatore. Considera questo programma:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Questo in realtà non verrà compilato qui (sto usando clang): il compilatore può rilevare il tentativo di modificare il tipo C primitivo ed emettere un errore. Ma ora confrontalo con questo programma:
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;
}
Anche se la funzione passa un puntatore costante a un oggetto costante, è ancora possibile modificare l'oggetto.
Nella programmazione orientata agli oggetti, il modo migliore per far rispettare la natura costante di un oggetto è rendere immutabile quell'oggetto - cioè non fornire alcun metodo che possa cambiare il suo stato. Immagina che la funzione precedente abbia preso un argomento NSString
invece di NSMutableString
e che io abbia passato il letterale @"Hello"
invece di una copia mutabile. Ora, a ragione, non c'è possibilità di mutare l'oggetto passato [*]. Objective-C non ha alcun modo di farle rispettare, a differenza dei riferimenti a const
o final
in altri linguaggi OO.
Per confronto, const
funziona in modo completamente diverso in C ++. Se ottengo un riferimento const
a un oggetto C ++, sono autorizzato a chiamare const
funzioni membro su quell'oggetto. Queste funzioni preservano const
-ness dell'oggetto, non apportando alcuna modifica o modificando solo le variabili membro che sono state esplicitamente contrassegnate mutable
dal progettista della classe. Quindi immagina di avere qualche tipo MutableString
in C ++ equivalente a NSMutableString
in Objective-C. L'equivalente del mio esempio sopra sarebbe simile a:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Questo sicuramente non verrà compilato: oltre a appendString()
non essendo un'operazione const
, la funzione rimuove il qualificatore const
dal riferimento al tipo che richiede const_cast
.
[*] Mi aspetto che ci sia un modo contorto di farlo, ma ora siamo nel regno di un programmatore che cerca di sabotare un altro facendo cose "intelligenti".