在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。
听说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。