我听说Objective-C受到"消息传递机制的影响" SmallTalk。
与Smalltalk一样,Objective-C可以使用动态类型:对象可以 发送了未在其界面中指定的消息。这可以允许 提高灵活性,因为它允许对象捕获"一个 消息并将消息发送到可以响应的其他对象 适当的消息,或同样将消息发送给另一个消息 对象
我觉得像[anObject someMethod]
这样的代码,someMethod
与机器代码的绑定可能会在运行时发生..
因此,我写了一个这样的演示:
#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中,方法的绑定是否真的发生在&#34;运行时&#34;?如果是这样,为什么会出现这样的编译器错误?
如果绑定没有发生在&#34;运行时&#34;,为什么&#34; Objective-C&#34;叫做#34;动态打字语言&#34;?
有没有人对此有任何想法?
答案 0 :(得分:0)
编译器的一项工作是在编译时捕获尽可能多的错误。如果它可以告诉调用在运行时失败,通常会让它抱怨。
您可以通过强制转换来抑制此操作,以显示运行时解析正在发生:
[(id)brad sayHelloTest];
答案 1 :(得分:0)
因为IDE可以从上下文中推断出明显的错误。
当你写if (a = 1)
时,你会收到警告。一个好的IDE应该帮助你尽早发现错误。
答案 2 :(得分:-1)
仅在过去五年内才有become a compiler error因为没有已知的方法声明。它与Automatic Reference Counting有关。在ARC下,编译器现在负责Cocoa使用的基于引用计数的内存管理。
鉴于责任,它必须能够在发送之前查看任何消息的方法声明,以便它知道哪些保留和发布是合适的。
方法解决方案(在类上查找方法)仍然在运行时发生,并且 - 特别是如果禁用ARC - 您仍然可以利用message forwarding
有关ARC的要求的一种方法是由Marcelo Cantos给出 - 将接收器投射到id
。另一种方法是使用performSelector:
。第三个 - 虽然我不推荐它 - 是直接使用objc_msgSend()
。
请注意,该方法的“绑定”在编译时发生并始终。在定义类时,方法与类相关联。 消息与方法不同,它们是在运行时解析到方法。
答案 3 :(得分:-1)
我终于找到了原因..
在编译期间抛出错误,因为包含-Werror
标记,这会将警告转换为错误 ..
http://clang.llvm.org/docs/UsersManual.html#cmdoption-Werror
删除-Werror
标志后,一切都按预期工作,错误只在运行时发生。