ใน Objective-C คุณไม่สามารถประกาศชื่อเมธอดโดยที่ส่วนประกอบสุดท้ายไม่รับอาร์กิวเมนต์ ตัวอย่างเช่นต่อไปนี้ผิดกฎหมาย
-(void)take:(id)theMoney andRun;
-(void)take:(id)yourMedicine andDontComplain;
เหตุใด Objective-C จึงออกแบบมาในลักษณะนี้ มันเป็นเพียงสิ่งประดิษฐ์ของ Smalltalk ที่ไม่มีใครเห็นว่าจำเป็นต้องกำจัด?
ข้อ จำกัด นี้มีความหมายใน Smalltalk เนื่องจาก Smalltalk ไม่มีตัวคั่นรอบการเรียกใช้ข้อความดังนั้นองค์ประกอบสุดท้ายจะถูกตีความว่าเป็นข้อความที่เป็นเอกภาพของอาร์กิวเมนต์สุดท้าย ยกตัวอย่างเช่นจะแยกวิเคราะห์เป็นBillyAndBobby take:'$100' andRun
BillyAndBobby take:('$100' andRun)
สิ่งนี้ไม่สำคัญใน Objective-C ที่ต้องใช้วงเล็บเหลี่ยม
การสนับสนุนส่วนประกอบตัวเลือกที่ไม่มีพารามิเตอร์จะไม่ช่วยให้เราได้รับประโยชน์มากนักในทุกวิธีการวัดภาษาตามปกติเนื่องจากชื่อวิธีการที่โปรแกรมเมอร์เลือก (เช่นrunWith:
แทนที่จะเป็นtake:andRun
) ไม่มีผลต่อความหมายเชิงฟังก์ชันของโปรแกรมหรือการแสดงออกของภาษา อันที่จริงโปรแกรมที่มีส่วนประกอบที่ไม่มีพารามิเตอร์นั้นเทียบเท่ากับอัลฟา ดังนั้นฉันจึงไม่สนใจคำตอบที่ระบุว่าคุณลักษณะดังกล่าวไม่จำเป็น (เว้นแต่เป็นเหตุผลที่ระบุไว้ของนักออกแบบ Objective-C ไม่มีใครรู้จัก Brad Cox หรือ Tom Love พวกเขามาที่นี่หรือไม่) หรือที่พูดว่า วิธีการเขียนชื่อเมธอดเพื่อไม่ให้คุณลักษณะนี้จำเป็น ประโยชน์หลักคือความสามารถในการอ่านและความสามารถในการเขียน (ซึ่งก็เหมือนกับความสามารถในการอ่านเพียง ... คุณรู้) เนื่องจากจะหมายความว่าคุณสามารถเขียนชื่อวิธีการที่คล้ายกับประโยคภาษาธรรมชาติได้ สิ่งที่ชอบ-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication
(ซึ่ง Matt Gallagher ชี้ให้เห็นเกี่ยวกับ "Cocoa With Love"-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed
ดังนั้นจึงวางพารามิเตอร์ถัดจากคำนามที่เหมาะสม
รันไทม์ Objective-C ของ Apple (ตัวอย่าง) สามารถจัดการตัวเลือกประเภทนี้ได้อย่างสมบูรณ์แบบแล้วทำไมไม่คอมไพเลอร์ล่ะ? ทำไมไม่สนับสนุนพวกเขาในชื่อวิธีการด้วย?
#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;
}