1

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?

Hanfei Sun
  • 42,165
  • 37
  • 115
  • 221
  • Yes it happen at run-time. And why you complaining that compiler helps you? – Cy-4AH Jan 11 '16 at 07:27
  • @Cy-4AH Because I don't think compiler should throw error for "run-time" errors. – Hanfei Sun Jan 11 '16 at 07:28
  • @Cy-4AH And how can the compiler know the message cannot be handled, or the method is not found? For dynamic language, the method can be redefined or appended dynamically to a Class, which the compiler may not be aware during the compiling stage – Hanfei Sun Jan 11 '16 at 07:32
  • You need look for `objective-c runtime reference`. You will find there all yours dynamic method redefenition and appendese. Compiler just add code, that call this functions for you and complains when it can't do something. – Cy-4AH Jan 11 '16 at 07:52

4 Answers4

0

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];
Marcelo Cantos
  • 174,413
  • 38
  • 319
  • 360
  • But how can the compiler know the message cannot be handled? For dynamic language, the method can be redefined or appended to a Class, which the compiler may not be aware during the compiling stage.. – Hanfei Sun Jan 11 '16 at 07:31
  • @hanfeisun Not in Objective-C afaik. But even if I'm wrong, I would rather the compiler play it safe and rely on the (id) escape hatch for the incredibly rare edge case. – Marcelo Cantos Jan 11 '16 at 07:35
  • I see.. But add `(id)` before `brad` still cannot suppress the compiler error.. ```main.m:24:15: error: instance method '-sayHelloTest' not found (return type defaults to 'id') [-Werror,-Wobjc-method-access] [(id)brad sayHelloTest]; ``` – Hanfei Sun Jan 11 '16 at 07:43
  • @hanfeisun: Sorry, I forgot that sayHelloTest has to be visible to the compiler as a valid method, even if not for the object in question. – Marcelo Cantos Jan 11 '16 at 08:02
0

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.

zhubch
  • 174
  • 1
  • 1
  • 8
-1

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.

Community
  • 1
  • 1
jscs
  • 63,095
  • 13
  • 148
  • 192
-1

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.

Hanfei Sun
  • 42,165
  • 37
  • 115
  • 221
  • I have the same question as yours. However `-Werror` only turns warnings into errors, so it means that the compiler still knows the object won't be able to respond to this specific message. So how did it know that? – Leo Aug 17 '16 at 07:33