在Objective-C中,方法的绑定是否真的发生在“运行时”?

我听说Objective-C受到SmallTalk的“消息传递机制”的影响。

与Smalltalk一样,Objective-C可以使用动态类型:可以向对象发送未在其接口中指定的消息。 这可以允许增加灵活性,因为它允许对象“捕获”消息并将消息发送到可以适当地响应消息的不同对象,或者同样将消息发送到另一个对象。

我觉得像[anObject someMethod]这样的代码, someMethod与机器代码的绑定可能会在运行时发生。

因此,我写了一个这样的演示:

 #import  @interface Person : NSObject { @private char *name; } @property (readwrite, assign) char *name; - (void)sayHello; @end @implementation Person @synthesize name; - (void)sayHello { printf("Hello, my name is %s!\n", [self name]); } @end int main() { Person *brad = [Person new]; brad.name = "Brad Cox"; [brad sayHello]; [brad sayHelloTest]; } 

我试过[brad sayHelloTest]brad发送一条消息sayHelloTestbrad不知道怎么处理..我希望错误不会在编译时发生..

但是,编译器仍然会抛出错误:

 main.m:24:11: error: instance method '-sayHelloTest' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access] [brad sayHelloTest]; ^~~~~~~~~~~~ main.m:3:12: note: receiver is instance of class declared here @interface Person : NSObject { ^ 

[(id)brad sayHelloTest]改为[(id)brad sayHelloTest]; 也不起作用..(编译命令是clang -Wall -Werror -g -v main.m -lobjc -framework Foundation -o main

在Objective-C中,方法的绑定是否真的发生在“运行时”? 如果是这样,为什么会出现这样的编译器错误?

如果绑定不是在“运行时”发生的,为什么“Objective-C”被称为“动态类型语言”?

有没有人对此有任何想法?

编译器的一项工作是在编译时捕获尽可能多的错误。 如果它可以告诉调用将在运行时失败,您通常希望它抱怨。

您可以通过强制转换来抑制此操作以显示运行时解析正在发生:

 [(id)brad sayHelloTest]; 

因为IDE可以从上下文中推断出明显的错误。

当你写if (a = 1) ,你会收到警告。 一个好的IDE应该可以帮助您尽早发现错误。

我终于找到了原因..

它在编译期间抛出错误,因为包含了-Werror标志,这会将警告变为错误

http://clang.llvm.org/docs/UsersManual.html#cmdoption-Werror

删除-Werror标志后,一切都按预期工作,错误只发生在运行时。

仅在过去五年内,由于没有已知的方法声明,它已成为编译器错误 。 它与自动参考计数有关 。 在ARC下,编译器现在负责Cocoa使用的基于引用计数的内存管理。

鉴于责任,它必须能够在发送之前查看任何消息的方法声明,以便它知道哪些保留和发布是合适的。

方法解析 (在类上查找方法)仍然在运行时发生,并且 – 特别是如果禁用ARC – 您仍然可以利用消息转发 。

围绕ARC的要求的一种方式是由Marcelo Cantos给出 – 将接收器强制转换为id 。 另一种是使用performSelector: . 第三个 – 虽然我不推荐它 – 是直接使用objc_msgSend()

请注意,该方法的“绑定”确实并且始终在编译时发生。 在定义类时,方法与类相关联。 消息与方法不同,它们在运行时解析为方法。