why casting does not change isa pointer - objective-c

id a = self->isa;
id b = ((NSObject*)self)->isa;
a and b holds same value.
Now given isa pointer is same, why does
[(Animal*)Person speakEnglish];
gives error? I thought casting will change isa pointer because if I cast a child class to it's parent class, I can not invoke the child's method anymore, and method invoke search is based on isa pointer.
I am interested to know how does method selector implemented, so that even isa pointer of an instance points to Person, If I call the Person's method of the instance, I will get an error.

I assume the Animal has no method -speakEnglish, but the original class of Person has.
Then, you get a compiler error, since the method is no declared. Please note, that (as #jrturton and #xlc0212 has mentioned) the compiler does not know anything about the runtime.
It may be possible that the object (at runtime) has a selector that can be called:
[(Animal*)Person performSelector: #selector(speakEnglish)];
This uses runtime data. More precisely, it checks if a method implementation is connected with this selector and calls this implementation.
However, there is no way the compiler can know since the compiler relies on static type information. Thus, you should provide the proper type information. But you do the opposite: you throw away the correct type.

Related

How does sending messages to classes work?

I know that you send messages to objects using [ ], and it is then translated to objc_msgSend()which needs a pointer to object as its first argument and second argument needs a selector.
But what about messaging classes like
[myClass doSomething];
It is not a pointer to object, so how does it work?
I am assuming that myClass is (literally) the name of a class (though usually classes start with a capital letter; I'll assume this is a class that doesn't follow the naming convention).
There are two cases of the message sending syntax in Objective-C. One, which you referred to, is if the left side is an expression which evaluates to a pointer to an object; the message is sent to that object. The second, is if the left side is an identifier which is the name of a class, then the compiler will send the message to the class object for that class. More technically, the compiler will pass a pointer to the class object as the first argument to objc_msgSend(). This is possible since it is the compiler which arranges the structure and location of the class object for each class, so it knows the address of that class object.
Intuitively, you can think of [myClass doSomething]; as similar to
Class foo = objc_getClass("myClass");
[foo doSomething];
or
Class foo = NSClassFromString(#"myClass");
[foo doSomething];
except that it doesn't need to do a runtime lookup to get a pointer to the class object -- the compiler knows the pointer at compile time.
Mike Ash has a great explanation of how objc_msgSend works: Friday Q&A 2012-11-16: Let's Build objc_msgSend.
Actually, when you send a message to a class, you are actually sending that message to a class object, which behaves as any other object with some limitations.
From Apple's reference:
In Objective-C, a class is itself an object with an opaque type called
Class. Classes can’t have properties defined using the declaration
syntax shown earlier for instances, but they can receive messages.
The runtime converts the message to a SEL then checks to see if that class responds to a message with that SEL including superclass inherited methods. If it responds it will perform the method.

How does objective-c handle method resolution at run-time?

I've read here recently that an objective-c object is stored on the heap as a struct. The struct contains the objects iVars, inherited iVars, and the isa pointer.
I'm trying to figure out when I send a message to this object, how does the run-time figure out the code to run?
I know there is a class object for each class. Is this also stored on the heap?
I think the way it works is that the run-time gets the isa pointer from the struct, uses this to call the message on the class object. Is this correct?
In short, every Objective-C instance has a pointer to its class. The class contains an inventory of metadata that includes all the methods that the class implements. When a message is sent to an object -- when a method is called -- the runtime uses the pointer to the class to lookup the method by name and call it, if it can be found. If it isn't found, the runtime looks to the superclass (which is a part of each class's metadata) on up the inheritance chain to NSObject. If the method ultimately can't be found, the runtime goes through a series of last ditch efforts to see if their is an alternative handler and eventually raises an exception, if not.
If you want more detail than that, I wrote up a multipart tour of exactly how Objective-C method dispatch works. It is slightly out of date -- doesn't deal with ARC, tagged pointers or blocks-as-IMP -- but still fully applicable.
Yes, classes are stored in the heap, but generally not in malloc()d memory. Classes are generally loaded as read-only, shared, memory. That is, there will be only one copy of the NSString class in memory for all applications running on the system. You can dynamically create classes on the fly and these will be in the regular heap, but it is atypical.

Call method in another class by Casting?

Ok so lets say I have Class A and Class B. In Class A lets say I implemented a method called saveImage and implemented the method in the .m.
Is it simple enough to say that if I do [(ClassA*)self saveImage]; That method in Class A will get called?
What is the logic behind this and can anyone explain it so I can understand a bit better?
Thanks!
Casting is mostly just for compile-time type checking (note that for safety, it's always wise to cast when you send a message to an object of type id. See here. It's ignored by the compiler (and therefore the runtime). Casting is just a promise to the compiler that yes, that object is really is really Class A, not Class B. So if you tried to compile that, unless self is actually an instance of Class A or a subclass (as you promised), you're going to raise an exception. AKA the runtime will get mad if you break your promises :)

Understand Objective-C runtime

I have read about how Objective-C runtime works, so please comment if I misunderstood something.
Let's say I have class called Person. That class may or not have method getSex.
Person *p = [[Person alloc]init];
Here the memory is allocated for Person instance (isa is created also which points to class Person), init is used to initialize Person ivar's
[p getSex];
Here objc_msgSend(Person,#selector(getSex) is called on Person class.
If Person class not have such method the runtime look for that method in Person root class and so on. When the method is found IMP is called which is a pointer to method block code. Then the method is executed.
Is that correct ?
Yes, everything is correct, except the behavior of init may or may not initialize all its member variables such that the accessors return valid results, although it is reasonable to guess that it initializes properties unless told otherwise.
There's one piece that's slightly off.
The call will actually be one of these three:
objc_msgSend(p, #selector(getSex))
objc_msgSend_fpret(p, #selector(getSex))
objc_msgSend_stret(p, #selector(getSex))
One difference here is that the first argument is to the object and not to the class.
Also, since you didn't share what the getSex method returns, it's not possible for us to know whether it will be one of the fpret/stret versions or not. If the method returns a double (on certain platforms), the fpret version will be used. If the method returns a structure value (on certain platforms), then the stret version will be used. All others will use the standard version. All of this is platform dependent in many different ways.
As the others said, allocation will create an object with all instance variables set to 0/NULL and a valid isa pointer as well. Initialization methods may or may not update the instance variables with something meaningful.

What's the difference between a method and a selector?

What the difference between a method, a selector and a message in Objective-C?
This is a great question.
Selector - a Selector is the name of a method. You're very familiar with these selectors: alloc, init, release, dictionaryWithObjectsAndKeys:, setObject:forKey:, etc. Note that the colon is part of the selector; it's how we identify that this method requires parameters. Also (though it's extremely rare), you can have selectors like this: doFoo:::. This is a method that takes three parameters, and you'd invoke it like [someObject doFoo:arg1 :arg2 :arg3]. There's no requirement that there be letters before each part of the selector components. As I said, this is extremely rare, and you will not find it used in the Cocoa frameworks. You can work with selectors directly in Cocoa. They have the type SEL: SEL aSelector = #selector(doSomething:) or SEL aSelector = NSSelectorFromString(#"doSomething:");
Message - a message is a selector and the arguments you are sending with it. If I say [dictionary setObject:obj forKey:key], then the "message" is the selector setObject:forKey: plus the arguments obj and key. Messages can be encapsulated in an NSInvocation object for later invocation. Messages are sent to a receiver. (ie, the object that "receives" the message).
Method - a method is a combination of a selector and an implementation (and accompanying metadata). The "implementation" is the actual block of code; it's a function pointer (an IMP). An actual method can be retrieved internally using a Method struct (retrievable from the runtime).
Some other related things that you didn't ask for:
Method Signature - a method signature represents the data types returned by and accepted by a method. They can be represented at runtime via an NSMethodSignature and (in some cases) a raw char*.
Implementation - the actual executable code of a method. Its type at runtime is an IMP, and it's really just a function pointer. iOS 4.3 includes a new ability to turn a block into an IMP. This is really cool.
One of the fun things to realize is that the name of a method (the selector) is distinct from the implementation of the method (the IMP). This means that you can swap them around, if you're feeling daring. You can also add and remove methods at runtime, because all you're doing is editing an entry in a hash table: the key is the selector, and the value is the IMP of the method. This allows you to do some really crazy and trippy stuff. It's not for the faint of heart. :)
A method is the implementation which is run when an object or class is asked to perform some action. It is in the scope of its containing class and is therefore different when referenced through some other class. A selector is an identifier which represents the name of a method. It is not related to any specific class or method, and can be used to describe a method of any class, whether it is a class or instance method.
Simply, a selector is like a key in a dictionary. It can tell you what method someone is talking about, but only if you also have the dictionary itself (the class or object). The method is what you get when you ask for the value from the dictionary using the selector as a key.
This site has a good overview of all the terminology in question: http://www.otierney.net/objective-c.html
Check out the link, but I'll give a quick summary:
A method is essentially like a method of function that you are used to in your favourite programming language.
A message (from the article) "A message can be dynamically forwarded to another object. Calling a message on an object in Objective-C doesn't mean that the object implements that message, just that it knows how to respond to it somehow via directly implementing it or forwarding the message to an object that does know how to."
Selectors can mean two things. It can refer to the name of a method, or "refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL." (from: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocSelectors.html)