Do cách thức hoạt động của các đối tượng Objective-C, const
từ bỏ việc thực thi và bắt đầu trở thành một ký hiệu cho lập trình viên. Hãy xem xét chương trình này:
int f(const int x) {
return ++x;
}
int main(int argc, char *argv[]) {
@autoreleasepool {
int x = 3;
NSLog(@"%d", f(x));
}
return 0;
}
Điều đó thực sự sẽ không được biên dịch ở đây (tôi đang sử dụng clang): trình biên dịch có thể phát hiện nỗ lực sửa đổi loại C nguyên thủy và phát ra lỗi. Nhưng bây giờ so sánh nó với chương trình này:
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;
}
Mặc dù hàm được truyền một con trỏ không đổi đến một đối tượng không đổi, nhưng vẫn có thể biến đổi đối tượng.
Trong lập trình hướng đối tượng, cách tốt nhất để thực thi tính chất không đổi của đối tượng là làm cho đối tượng đó không thay đổi - tức là không cung cấp bất kỳ phương thức nào có thể thay đổi trạng thái của nó. Hãy tưởng tượng rằng hàm trên đã lấy một NSString
đối số thay vì NSMutableString
và tôi đã chuyển qua nghĩa đen @"Hello"
thay vì một bản sao có thể thay đổi. Hiện tại, nói một cách hợp lý, không có cơ hội đột biến đối tượng truyền vào [*]. Objective-C không có bất kỳ cách nào để thực thi điều đó, không giống như const
hoặc final
tham chiếu đối tượng trong các ngôn ngữ OO khác.
Để so sánh, const
hoạt động hoàn toàn khác nhau trong C ++. Nếu tôi nhận được một const
tham chiếu đến một đối tượng C ++, tôi chỉ được phép gọi các const
hàm thành viên trên đối tượng đó. Các hàm này bảo vệ tính const
chất của đối tượng, bằng cách không thực hiện bất kỳ thay đổi nào hoặc chỉ sửa đổi các biến thành viên đã được đánh dấu rõ ràng mutable
bởi trình thiết kế lớp. Vì vậy, hãy tưởng tượng rằng tôi đã có một số loại MutableString
trong C ++ tương đương với NSMutableString
Objective-C. Tương đương với ví dụ của tôi ở trên sẽ trông giống như:
MutableString& f3(const MutableString& x) {
x.appendString(" world!");
return x;
}
Điều này chắc chắn sẽ không được biên dịch: ngoài việc appendString()
không phải là một const
hoạt động, hàm sẽ loại bỏ const
vòng loại khỏi tham chiếu loại yêu cầu a const_cast
.
[*] Tôi hy vọng có một số cách làm trái ngược, nhưng bây giờ chúng ta vào vương quốc của một lập trình viên đang cố gắng phá hoại người khác bằng cách làm những việc "thông minh".