Is it possible to force Objective-C to call a specific instance of a virtual method, rather than going through the standard virtual message dispatch? I know this is generally a Bad Idea, but I'd like to know how to do it using the Objective-C runtime.
For example, given class A and B that implement -(void) foo, where B is a subclass of A, I'd like to call the foo method on A with the B instance (even though B would normally handle this message).
I know that I can make this happen by moving the guts of A's foo method to a new method and delegating to it, but I'd like to figure out some way to do this through the Objective-C runtime.
NOTE: For the purposes of this question, assume that I can't change the source of A or B and I've carefully weighed the risks of breaking encapsulation.
This page is a great source for understanding the runtime; a quick memory-assisted scan shows that the section titled "So what happens in objc_msgSend anyway?" is a good place to start for an immediate answer, but the article as a whole will really help you understand what goes on.
Here's an example where he queries the runtime for the appropriate function pointer, then calls the function directly:
//declare C function pointer
int (computeNum *)(id,SEL,int);
//methodForSelector is COCOA & not ObjC Runtime
//gets the same function pointer objc_msgSend gets
computeNum = (int (*)(id,SEL,int))[target methodForSelector:#selector(doComputeWithNum:)];
//execute the C function pointer returned by the runtime
computeNum(obj,#selector(doComputeWithNum:),aNum);
What Matthias said... however:
For example, given class A and B that implement -(void) foo, where B
is a subclass of A, I'd like to call the foo method on A with the B
instance (even though B would normally handle this message).
In other words, you have an implementation of foo on B that you want to avoid by calling a's implementation directly?
Obviously, if you are the implementer of B, then this is trivial; just implement the appropriate logic to determine when it is needed and call [super foo];.
If you are not the implementer of B, then this is beyond a bad idea. It is pretty much guaranteed to lead to mystery crashers and/or misbehavior. Worse, if B is actually a part of a system framework or something that may be updated via a mechanism other than your app being updated, then you have a ticking time bomb that may start crashing your app at any time on any random configuration of the OS.
Specifically:
B's foo may not be self contained; it may do stuff before/after calling A's foo that sets up internal state that may later be required for continued correct operation. You are breaking encapsulation with a sledgehammer.
calling the implementation directly is going to bypass any KVO in play. Unless you happen to grab a derived method implementation, at which point, your behavior is going to explode when that derived method should no longer be in play.
Related
I'm new to Objective-C and was wondering if anyone could provide any information to clarify this for me. My (possibly wrong) understanding of object instantiation in other languages is that the object will get it's own copies of instance variables as well as instance methods, but I'm noticing that all the literature I've read thus far about Objective-C seems to indicate that the object only gets copies of instance variables, and that even when calling an instance method, program control reverts back to the original method defined inside the class itself. For example, this page from Apple's developer site shows program flow diagrams that suggest this:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Also in Kochan's "Programming in Objective-C", 6th ed., pg. 41, referring to an example fraction class and object, the author states that:
"The first message sends the setNumerator: message to myFraction...control is then sent to the setNumerator: method you defined for your Fraction class...Objective-C...knows that it's the method from this class to use because it knows that myFraction is an object from the Fraction class"
On pg. 42, he continues:
"When you allocate a new object...enough space is reserved in memory to store the object's data, which includes space for its instance variables, plus a little more..."
All of this would seem to indicate to me that there is only ever one copy of any method, the original method defined within the class, and when calling an instance method, Objective-C simply passes control to that original copy and temporarily "wires it" to the called object's instance variables. I know I may not be using the right terminology, but is this correct? It seems logical as creating multiple copies of the same methods would be a waste of memory, but this is causing me to rethink my entire understanding of object instantiation. Any input would be greatly appreciated! Thank you.
Your reasoning is correct. The instance methods are shared by all instances of a class. The reason is, as you suspect, that doing it the other way would be a massive waste of memory.
The temporary wiring you speak of is that each method has an additional hidden parameter passed to it: a pointer to the calling object. Since that gives the method access to the calling object, then it can easily access all of the necessary instance variables and all is well. Note that any static variable exists in only a single instance as well and if you are not aware of that, unexpected things can happen. However, regular local variables are not shared and are recreated for each call of a method.
Apple's documention on the topic is very good so have a look for more info.
Just think of a method as a set of instructions. There is no reason to have a copy of the same method for each object. I think you may be mistaken about other languages as well. Methods are associated with the class, not individual objects.
Yes, your thinking is more or less right (although it's simpler than that: behind the scenes in most such languages methods don't need to be "wired" to anything, they just take an extra parameter for self and insert struct lookups before references to instance variables).
What might be confusing you is that not all languages work this way, in their implementations and semantically. Object-oriented languages are (very roughly) divided into two camps: class-based, like Objective-C; and prototype-based, like Javascript. In the second camp of languages, a method or procedure really is an object in its own right and can often be assigned directly to an object's instance variables as well - there are no classes to lookup methods from, only objects and other objects, all with the same first-class status (this is an oversimplification, good languages still allow for sharing and efficiency).
my question as the title says.obviously, the first parameter was used for this pointer , in some taste of c++.what about the second one? thak you.
The signature of objc_msgSend() is:
id objc_msgSend(id self, SEL op, ...);
Every method call is compiled down to a call to this function. I.e., if you call:
[anArray objectAtIndex:42];
That will be compiled as if it were:
objc_msgSend(anArray, #selector(objectAtIndex:), 42);
Now, to your question, why do methods get compiled down to a function that has the SEL as the second argument. Or, more specifically, why is this method:
- (id)objectAtIndex:(NSUInteger)index;
Exactly equivalent to this C function:
id object_at_index(id object, SEL _cmd, NSUInteger index);
The answer is speed speed speed.
Speed
Specifically, by doing this, then objc_msgSend() never has to rewrite the stack frame* and it can also use a tail call optimization to jump directly to the method invocation. This is the same reason why you never see objc_msgSend() in backtraces in the debugger (save for when you actually crash/break in the messenger).
objc_msgSend() uses the object and the _cmd to look up the implementation of the method and then, quite literally, jumps to that implementation.
Very fast. Stack frame untouched.
And, as others have stated, having _cmd around in the method implementation can be handy for a variety of reasons. As well, it also means that the messenger can do neat tricks like proxy support via NSInvocation and the like.
*rewriting the stack frame can be insanely complex and expensive. Some of the arguments might be in registers some of the time, etc... All architecture dependent ABI nastiness. One of the biggest challenges to writing things like imp_implementationWithBlock() was figuring out how to do so without touching the stack because doing so would have been too slow and too bloated to be viable.
The purpose of having the second parameter contain the selector is to enable a common dispatch mechanism. As such, the method dispatch code always expects the second parameter to be the selector, and dispatches based on that, or follows the inheritance chain up, or even creates an NSInvocation and calls forwardInvocation:.
Generally, only system-level routines use the selector argument, although it's rather nice to have it when you hit an exception or are in the debugger trying to figure out what routine is giving you difficulties if you are using forwardInvocation
From the documentation:
Discussion
This data type is a pointer to the start of the function that implements the method. This function uses standard C calling conventions as implemented for the current CPU architecture. The first argument is a pointer to self (that is, the memory for the particular instance of this class, or, for a class method, a pointer to the metaclass). The second argument is the method selector. The method arguments follow.
In Objective-C when you call a method you need to know the target, the selector and the eventual arguments. Let's suppose that you are trying to do this manually: how can you know which method to call if you don't know the selector? Do you call some random method? No, you call the right method because you know the method name.
I have a class, call it A that parses some data out in an NSDictionary. That class has a table view, and when a cell is selected, a new class instantiates, let's call that class B. Class B in turn instantiates class C. I want class C to receive the NSDictionary that was created in A.
Would delegates work? Would it work even though class C isn't instantiated? If that's true and it really does not, should I pass the data from A-->B-->C in the init method? Are there better message passing methods in Objective-C?
should I pass the data from A-->B-->C in the init method?
I think that's the best plan.
A really shouldn't have to worry about how B does what it does. The fact that B uses C is none of A's business. All A needs to know is that B needs the dictionary in order to do it's thing.
As it happens, B doesn't care all that much about the dictionary, but the dictionary should be part of B's job description, which is something like: Take the data you're given and display it somehow. If B deals with the dictionary by passing it directly to C, that's fine -- not something A should care about.
You could do the same thing with a delegate. A could give B a reference to itself as a data source, and B could eventually pass that on to C. It's the same process you'd have with the dictionary, so there's no real advantage in doing that if you can put everything that C needs into the dictionary. You might consider switching to delegation if A doesn't know in advance exactly what data is needed, or when you want A to be able to somehow customize the behavior of C.
I would go with passing it through the init. Alternatively depending on what kind of class "A" is. You could make it a singleton, or pass the parsed dictionary to a singleton, and then reference it directly from within "C".
I know that in Objective C, every object has first 4 bytes [depending upon type of processor ] as an isa pointer stored in it that tells which class it belongs to and what dispatch table to use to resolve a selector to address of a function.
What I wanted to know was , how are data members stored and accessed in these methods.
self is passed as an implicit object in each function being called.
We use setters n getters to handle data members in other member function as a good practice,
but when we directly refer to a data member in an initializer or an accesor, how are they accessed. Are they replaced by some address at compile time or something else ?
Actually afaik the memory layout is implementation specific, but http://algorithm.com.au/downloads/talks/objective-c-internals/objective-c-internals.pdf should give you a pretty good idea of the inner works of object data and object messaging.
When you use a direct member access, what basically happens is that you're fetching straight from the "struct" that is your actual object. That is, the compiler is basically just adding an offset to the address of your object/struct and reading the contents of that memory address.
Maybe I should add that this is reverse engineered from XCode and not written in any specification I can find, so depending on this behavior is most likely a bad idea. Since external access to the iVars is not allowed, the decision is basically up to the compiler and could be changed at any time.
Edit: as #FrederickCheung points out, Objective C 2.0 may have changed this behavior.
It's not as simple as a compile time offset calculation, at least not in objective C 2.0 on the 64bit OS X and iOS runtimes. These support stuff like superclasses changing their instance variable layout without breaking subclasses that were compiled against the old layout by adding a layer of indirection.
The runtime api docs describe the API one can use to set instance variables and so on but doesn't elaborate on their implementation.
I have been reading Apple's "The Objective-C Programming Language", I noticed that if you have say,
Class A /w methods MA and MB, where MA calls MB with "[self MB]".
If you subclass Class A, lets call it SubClass A, and over-ride MB. Made an instance of SubClass A and call MA, it will use the new MB. Now if you call "[super MA]" instead, it will still use the new MB.
Am I correct?
So I was wondering if "self" is the "right" way to go about this, calling other methods in the same instance, or if it's only used for special situations like covering initializers.
Yes, self is the right way to send a message to the same instance that the method is executing on.
One of the big things to keep in mind about the object model of languages like Objective-C is that, conceptually, you are not "calling methods" — you're sending messages. You're telling the object what to do, not how to do it. You shouldn't normally have to think about what precise method will execute when you send a message — the object is expected to respond appropriately. So if somebody has overridden this "MB" method, presumably the new behavior is how he wants the object to respond when it gets an "MB" message. If somebody has overridden "MB" such that it is no longer usable the way the old method was, then that sounds like a bug.
Yes it is.
Using self inside your class is the right way to go if you want to call methods that are in the same class.
'self' represents the current instance of the class where you are using it.
self is the right way to go. Every method in Objective-C can be thought of as "virtual" (in C++ parlance).
In SubClass A, you don't need to make an instance, you can access any function of subClass A by sing self.
making new object makes a new instance, so it reintialize all the property for that instance.
so you can't do any thing right with this.
self always be right for accessing same class methods and property.
Hope now you can understand why self rather than making other new instance.
And [super MA] must call method of class A's MA method, no case in which MB calls for calling MA.
I have test it, there is no bug all OOPs concept follow in objective c you can call super class method by calling method on super keyword.
So Probably you are doing some thing wrong. just check it.