Re: Newbie question on Methods
Re: Newbie question on Methods
- Subject: Re: Newbie question on Methods
- From: Erik Buck <email@hidden>
- Date: Sun, 12 Mar 2006 13:00:00 -0500
There is one concept I'm not understanding. In the
NSOpenPanelWithFileTypes example (on CocoaDev.com) there is the
following code:
NSArray *fileTypes = [NSArray arrayWithObject:@"td"];
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
This is the central concept of Objective-C. I am unlikely to be able
to improve on the documentation and many available books in this
email. Nevertheless, I will try :)
As a C programmer, perhaps you need the "magic" removed so you can
see what is happening in Objective-C.
Objective-C adds the concepts of objects and message sending to the C
language. Any message may be sent to any object. By default, there
is a runtime error if the receiver of a message does not understand
the message, although some receivers may suppress the error or handle
the unrecognized message my passing it on to an object that does
understand it.
Because you are an avowed C programmer, I intend to describe the
concept of Objective-C objects from a C point of view. But first,
let me propose these implementation neutral definitions: An Objective-
C object is anything that can receive a message. A message is just a
request for the receiver to do something using arguments that may be
provided with the message. In some cases, sending a message may
return a value to the sender.
Those definitions may seem vague, but it is that simple, and there
are huge implications to this. Just to whet you appetite, let me
start by saying that neither the receiver nor the message needs to be
known at compile time, and this is the great strength (flexibility)
of Objective-C and similar languages like Smalltalk, Ruby, and Python
but not like C++ or Java.
So, for a C programmer, what is an Objective-C object ? In
implementation, and Objective-C object is any C structure whose first
element is a variable of type Class. In objc.h on you hard drive,
you will find the C type Class is declared as
typedef struct objc_class *Class;
Another fun C typedef is the id type used to store a pointer to any
Objective-C object:
typedef struct objc_object {
Class isa;
} *id;
So, any variable of type id is just a pointer to any structure that
contains as its first element a pointer to a variable of type Class.
Now that you know exactly what an Objective-C object is from a C
programmer's point of view, what is a message ?
Objective-C's implementation provides a couple of C functions:
id objc_msgSend(id self, SEL op, ...);
id objc_msgSendSuper(struct objc_super *super, SEL op, ...);
The SEL type is the C type that identifies what message is being
sent. In objc_msgSend(id self, SEL op, ...), self is the receiver of
the message, SEL identifies the message being sent, and any number of
arguments may follow.
objc_msgSendSuper() is similar to objc_msgSend(). The only relevant
difference between the two is where the function looks first to find
an IMP to call in response to the message. What's an IMP you ask ?
typedef id (*IMP)(id, SEL, ...);
IMP is a C typedef for a pointer to a function that takes the same
arguments as objc_msgSend() and returns the same type. The code that
is executed in response to receipt of an Objective-C message is
compiled into a C function by the Objective-C compiler. Pointers to
those functions are then associated with messages using a hash table
that maps SEL to IMP.
objc_msgSend() and objc_msgSendSuper() simply use the provided SEL
argument to look-up the corresponding IMP and than call the IMP
passing the same arguments that were passed to objc_msgSend() and
objc_msgSendSuper().
That is Objective-C.
---------------------
Now that you know what an object is, let's look at your question again.
NSArray *fileTypes = [NSArray arrayWithObject:@"td"];
NSOpenPanel *oPanel = [NSOpenPanel openPanel];
NSArray * and NSOpenPanel * are both synonyms for the C type id.
The following code will produce EXACTLY the same machine code when
compiled with Objective-C as the code in your example:
id fileTypes = [NSArray arrayWithObject:@"td"];
id oPanel = [NSOpenPanel openPanel];
So you know that fileTypes is a variable that points to a struct
objc_object.
You wrote:
I understand that in the first line you are declaring an instance of
the class (fileTypes) of the NSArray object. But I don't understand
***** You misunderstood! You were not declaring an instance of class
fileTypes. In fact, your statement of understanding was completely
non-sensical. All you did was declare a variable that will point to
a struct objc_object and then initialize that variable with whatever
the result of [NSArray arrayWithObject:@"td"] turns out to be.
id fileTypes = [NSArray arrayWithObject:@"td"]; is a synonym for
id fileTypes = objc_msgSend(objc_lookUpClass("NSArray"), sel_getUid
("arrayWithObject:"), @"td");
For reference: In objc.h see the declaration SEL sel_getUid(const
char *str);
In objc-runtime.h see the declaration id objc_lookUpClass(const char
*name);
ignoring @"td" for a moment (it was another of your questions)...
you now see that id fileTypes = [NSArray arrayWithObject:@"td"]; is
just a syntactically nicer way of writing id fileTypes = objc_msgSend
(objc_lookUpClass("NSArray"), sel_getUid("arrayWithObject:"), @"td");.
In reality, the Objective-C compiler can optimize things a bit to
eliminate some of the function calls at run-time, but that is beside
the point right now.
What is the significance of the string "NSArray" ? There is an
Objective-C class named NSArray provided by the Cocoa framework. As
you can guess from the C language implementation of Objective-C,
objc_lookUpClass() just returns an id type value that was associated
with the string "NSArray" by the Objective-C compiler. Yes, that's
right, just like the compiler generates a hash table to associate IMP
with SEL, it generates a hash table to associate ids with Objective-C
class names like "NSArray." So, when the compiler compiled the class
NSArray, the compiler generated the following things:
1) the compiler generated a static C structure whose first element is
of type Class.
2) the compiler generated a hash table entry associating a pointer to
the static structure with the string "NSArray."
3) the compiler generated a hash table entry associating a SEL with
the string "arrayWithObject:"
3) The compiler generated a C function containing code to be executed
in response to the arrayWithObject: message selector.
4) the compiler generated a hash table entry associating a pointer to
the generated function with the SEL previously associated with the
string "arrayWithObject:".
All that stuff generated by the compiler makes id fileTypes =
objc_msgSend(objc_lookUpClass("NSArray"), sel_getUid
("arrayWithObject:"), @"td") work at run-time.
Stay tuned for more...
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden