Ze względu na sposób, w jaki działają obiekty Objective-C, constrezygnuje z wymuszania i zaczyna być notacją dla programisty. Rozważ ten program:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
To się właściwie nie kompiluje (używam clang): kompilator może wykryć próbę zmodyfikowania pierwotnego typu C i generuje błąd. Ale teraz porównaj to z tym programem:
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;
}
Mimo że funkcja jest przekazywana do stałego obiektu przez stały wskaźnik, nadal można mutować obiekt.
W programowaniu obiektowym najlepszym sposobem na wymuszenie stałej natury obiektu jest uczynienie go niezmiennym - tzn. Brak metod, które mogłyby zmienić jego stan. Wyobraź sobie, że powyższa funkcja wzięła NSStringargument zamiast NSMutableString, i że przekazałem literał @"Hello"zamiast modyfikowalnej kopii. Zasadniczo nie ma teraz szansy na mutację przekazywanego obiektu [*]. Objective-C nie ma żadnego sposobu egzekwowania tego jednak, w przeciwieństwie do constlub finalodwołań do obiektów w innych językach oo.
Dla porównania constdziała zupełnie inaczej w C ++. Jeśli otrzymam constodwołanie do obiektu C ++, będę mógł wywoływać constfunkcje składowe tylko na tym obiekcie. Funkcje te chronią const-ness obiektu, albo nie dokonując żadnych zmian, albo tylko modyfikując zmienne składowe, które zostały wyraźnie oznaczone mutableprzez projektanta klasy. Więc wyobraź sobie, że miałem jakiś typ MutableStringw C ++, który jest równoważny NSMutableStringw Objective-C. Odpowiednik mojego powyższego przykładu wyglądałby mniej więcej tak:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
To na pewno się nie skompiluje: oprócz appendString()tego, że nie jest constoperacją, funkcja usuwa constkwalifikator z odwołania do typu, który wymaga znaku const_cast.
[*] Spodziewam się, że istnieje jakiś zniekształcony sposób, ale teraz jesteśmy w królestwie jednego programisty, który próbuje sabotować drugiego, robiąc „sprytne” rzeczy.