首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Objective-C方法名的最后一部分必须带参数(当有多个部分时)?

为什么Objective-C方法名的最后一部分必须带参数(当有多个部分时)?
EN

Stack Overflow用户
提问于 2010-12-19 04:18:57
回答 3查看 10.3K关注 0票数 90

在Objective-C中,你不能在最后一个组件不带参数的地方声明方法名。例如,以下内容是非法的。

代码语言:javascript
复制
-(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)既不会影响程序的函数语义,也不会影响语言的表现力。实际上,一个有无参数组件的程序与没有参数组件的程序是alpha等价的。因此,我对不需要这样一个特性的回答不感兴趣(除非这是Objective-C设计者陈述的原因;有人碰巧认识Brad Cox或Tom Love吗?他们在这里吗?)或者说明如何编写方法名称,以便不需要该功能。它的主要优点是可读性和可写性(就像可读性,只是...您知道),因为这意味着您可以编写更接近自然语言句子的方法名称。像-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication*)theApplication这样的( Matt Gallagher指出,当您删除形式参数时,on "Cocoa With Love"有点令人困惑)可以将其命名为-(BOOL)application:(NSApplication*)theApplication shouldTerminateAfterLastWindowClosed,从而将参数放在适当的名词旁边。

Apple的Objective-C运行时(例如)完全能够处理这类选择器,那么为什么编译器不能呢?为什么不在方法名中也支持它们呢?

代码语言:javascript
复制
#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;
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-12-20 05:57:17

我是布拉德·考克斯。我最初的回答误解了这个问题。我假设reallyFast是一个硬编码的扩展,用来触发更快的消息传递,而不是一种语法糖。真正的答案是Smalltalk不支持它,可能是因为它的解析器不能处理(假设的)歧义。虽然OC的方括号可以消除任何歧义,但我根本没有想过要偏离Smalltalk的关键字结构。

票数 111
EN

Stack Overflow用户

发布于 2010-12-19 05:20:44

仅供参考,运行库实际上并不关心选择器,任何C字符串都是有效的,你也可以像这样做一个选择器:“==+=+-__--?:”如果没有参数,运行库就会接受它,编译器就不能接受它,否则它就不可能解析。当涉及到选择器时,绝对没有健全的检查。

票数 21
EN

Stack Overflow用户

发布于 2010-12-19 04:26:31

我假设它们在Objective-C中不受支持,因为它们在Smalltalk中也不可用。但这有一个与你想象的不同的原因:它们是不需要的。需要的是支持0,1,2,3,...参数。对于每一个数量的参数,已经有了一个有效的语法来调用它们。添加任何其他语法只会造成不必要的混乱。

如果你想要多个单词的无参数选择器,为什么只有一个额外的单词呢?然后有人可能会问

代码语言:javascript
复制
 [axolotl perform selector: Y with object: Y]

也变得受支持(即选择器是一个单词序列,其中一些包含冒号和参数,而其他则不是)。虽然这是可能的,但我假设没有人认为这是值得的。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4479967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档