Trong Objective-C, bạn không thể khai báo tên phương thức trong đó thành phần cuối cùng không nhận đối số. Ví dụ, sau đây là bất hợp pháp.
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
Tại sao Objective-C lại được thiết kế theo cách này? Nó chỉ là một đồ tạo tác của Smalltalk mà không ai thấy cần phải loại bỏ?
Hạn chế này có ý nghĩa trong Smalltalk, vì Smalltalk không có các dấu phân cách xung quanh lệnh gọi thông báo, vì vậy thành phần cuối cùng sẽ được hiểu là một thông báo một ngôi cho đối số cuối cùng. Ví dụ, BillyAndBobby take:'$100' andRun
sẽ được phân tích cú pháp là BillyAndBobby take:('$100' andRun)
. Điều này không quan trọng trong Objective-C, nơi bắt buộc phải có dấu ngoặc vuông.
Hỗ trợ các thành phần bộ chọn không tham số sẽ không giúp ích cho chúng tôi nhiều theo tất cả các cách thông thường mà một ngôn ngữ được đo lường, như tên phương thức mà lập trình viên chọn (ví dụ: runWith:
thay vìtake:andRun
) không ảnh hưởng đến ngữ nghĩa chức năng của một chương trình, cũng như tính biểu cảm của ngôn ngữ. Thật vậy, một chương trình có các thành phần không có tham số là alpha tương đương với một chương trình không có. Vì vậy, tôi không quan tâm đến những câu trả lời rằng một tính năng như vậy là không cần thiết (trừ khi đó là lý do đã nêu của các nhà thiết kế Objective-C; có ai tình cờ biết Brad Cox hoặc Tom Love không? Họ có ở đây không?) Hoặc nói rằng cách viết tên phương thức để tính năng không cần thiết. Lợi ích chính là khả năng đọc và khả năng ghi (giống như khả năng đọc, chỉ ... bạn biết), vì nó có nghĩa là bạn có thể viết các tên phương thức thậm chí gần giống với các câu ngôn ngữ tự nhiên hơn. Những thứ thích -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(mà Matt Gallagher chỉ ra trong "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
, do đó đặt tham số ngay bên cạnh danh từ thích hợp.
Thời gian chạy Objective-C của Apple (ví dụ) hoàn toàn có khả năng xử lý các loại bộ chọn này, vậy tại sao không phải là trình biên dịch? Tại sao không hỗ trợ chúng trong tên phương thức?
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface Potrzebie : NSObject
-(void)take:(id)thing;
@end
@implementation Potrzebie
+(void)initialize {
SEL take_andRun = NSSelectorFromString(@"take:andRun");
IMP take_ = class_getMethodImplementation(self, @selector(take:));
if (take_) {
if (NO == class_addMethod(self, take_andRun, take_, "@@:@")) {
NSLog(@"Couldn't add selector '%@' to class %s.",
NSStringFromSelector(take_andRun),
class_getName(self));
}
} else {
NSLog(@"Couldn't find method 'take:'.");
}
}
-(void)take:(id)thing {
NSLog(@"-take: (actually %@) %@",NSStringFromSelector(_cmd), thing);
}
@end
int main() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Potrzebie *axolotl=[[Potrzebie alloc] init];
[axolotl take:@"paradichloroaminobenzaldehyde"];
[axolotl performSelector:NSSelectorFromString(@"take:andRun")
withObject:@"$100"];
[axolotl release];
[pool release];
return 0;
}