在Objective-C中,方法的绑定真的发生在"run-time"吗?

In Objective-C, does the binding of method really happen at "run-time"?

听说Objective-C受到了SmallTalk的"message passing mechanism"的影响。

Objective-C, like Smalltalk, can use dynamic typing: an object can be sent a message that is not specified in its interface. This can allow for increased flexibility, as it allows an object to "capture" a message and send the message to a different object that can respond to the message appropriately, or likewise send the message on to another object.

而且我觉得像 [anObject someMethod] 这样的代码,someMethod 到机器码的绑定可能发生在 运行 时间..

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

#import <Foundation/Foundation.h>

@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 一条消息 sayHelloTest brad 不知道如何处理..我希望错误不会发生在编译时..

但是,编译器仍然报错:

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中,方法的绑定真的发生在"run-time"吗?如果是这样,为什么会出现这样的编译错误?

如果绑定没有发生在 "run-time",为什么 "Objective-C" 被称为 "dynamic typing language"?

有人对此有什么想法吗?

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

您可以通过强制转换来抑制它,以表明正在运行运行时解析:

[(id)brad sayHelloTest];

它有become a compiler error only within the last five years for there to be no known declaration of a method. It has to do with Automatic Reference Counting。在 ARC 下,编译器现在负责 Cocoa 使用的 reference-counting-based 内存管理。

鉴于该责任,它必须能够在发送消息之前查看任何消息的方法声明,以便它知道什么是适当的保留和释放。

resolution 方法(在 class 上查找方法)仍然会在运行时发生,并且——特别是如果你禁用 ARC——你可以还是趁着message forwarding.

Marcelo Cantos 给出了绕过 ARC 要求的一种方法——将接收器投射到 id。另一种是使用performSelector:。第三种——虽然我不推荐——是直接使用 objc_msgSend()

请注意,方法的“绑定”并且总是发生在编译时。当定义了 classes 时,方法与 classes 相关联。 消息与方法不同,它们在运行时解析到方法。

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

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

终于找到原因了..

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

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

在我删除 -Werror 标志后,一切正常,错误仅发生在 run-time。