A causa del modo in cui funzionano gli oggetti Objective-C, const
smette di essere un'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 emette 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 alla funzione viene passato un puntatore costante a un oggetto costante, è comunque possibile mutare l'oggetto.
Nella programmazione orientata agli oggetti, il modo migliore per imporre la natura costante di un oggetto è renderlo immutabile, ovvero non fornire alcun metodo che possa modificarne lo stato. Immagina che la funzione sopra abbia preso un NSString
argomento invece di NSMutableString
e che io abbia passato il letterale @"Hello"
invece di una copia mutabile. Non c'è ora, ragionevolmente parlando, nessuna possibilità di mutare l'oggetto passato [*]. Objective-C non ha alcun modo di far rispettare che però, a differenza const
o final
riferimenti agli oggetti in altri linguaggi OO.
Per fare un confronto, const
funziona in modo completamente diverso in C ++. Se ottengo un const
riferimento a un oggetto C ++, posso solo chiamare le const
funzioni membro su quell'oggetto. Queste funzioni preservano il const
carattere 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 un tipo MutableString
in C ++ equivalente a NSMutableString
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 essere const
un'operazione, la funzione rimuove il const
qualificatore dal riferimento di tipo che richiede un const_cast
.
[*] Mi aspetto che ci sia un modo contorto di farlo, ma ora siamo nei regni di un programmatore che cerca di sabotare un altro facendo cose "intelligenti".