In Objective-C, does the binding of method really

2019-03-01 10:14发布

问题:

I heard that Objective-C is influenced by the "message passing mechanism" of SmallTalk.

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.

And I felt for codes like [anObject someMethod], the binding of someMethod to the machine code may happen at run-time..

Therefore, I write a demo like this:

#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];


}

I tried [brad sayHelloTest] to send brad a message sayHelloTest which brad doesn't know how to handle with.. I expect the error will NOT happen at compile-time..

However, the compiler still throws an error:

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 {
           ^

Change [(id)brad sayHelloTest] to [(id)brad sayHelloTest]; doesn't work either.. (The compiling command is clang -Wall -Werror -g -v main.m -lobjc -framework Foundation -o main)

In Objective-C, does the binding of method really happen at "run-time"? If so, why will there be a compiler error like this?

If the binding doesn't happen at "run-time", why was "Objective-C" called "dynamic typing language"?

Does anyone have any ideas about this?

回答1:

One job of a compiler is to catch as many errors at compile time as possible. If it can tell that the call will fail at runtime, you generally want it to complain.

You can suppress this via casting to show that runtime resolution is happening:

[(id)brad sayHelloTest];


回答2:

Because the IDE can infer the obvious error from the context.

When you write if (a = 1),you will get a warning. A good IDE should help you find mistakes as early as possible.



回答3:

I figured out the reason finally..

It throw errors during compiling because -Werror flag is included, which will turn warning into error..

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

After I delete -Werror flag, everything works as expected and the error only happens at run-time.



回答4:

It has 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. Under ARC, the compiler is now responsible for the reference-counting-based memory management that Cocoa uses.

Given that responsibilty, it must be able to see the declarations of methods for any messages before they are sent, so that it knows what retains and releases are appropriate.

The method resolution (the lookup of the method on the class) does still happen at runtime, and -- particularly if you disable ARC -- you can still take advantage of message forwarding.

One way around ARC's requirement was given by Marcelo Cantos -- cast the receiver to id. Another is to use performSelector:. A third -- though I can't recommend it -- is to use objc_msgSend() directly.

Note that the "binding" of the method does, and always did, happen at compile time. Methods are associated with classes, when the classes are defined. Messages are distinct from methods, and it is they that resolve at runtime to a method.