Ze względu na sposób, w jaki działają obiekty Objective-C, const
rezygnuje 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 NSString
argument 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 const
lub final
odwołań do obiektów w innych językach oo.
Dla porównania const
działa zupełnie inaczej w C ++. Jeśli otrzymam const
odwołanie do obiektu C ++, będę mógł wywoływać const
funkcje 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 mutable
przez projektanta klasy. Więc wyobraź sobie, że miałem jakiś typ MutableString
w C ++, który jest równoważny NSMutableString
w 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 const
operacją, funkcja usuwa const
kwalifikator 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.