Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > introspection in ObjC

introspection in ObjC
Thread Tools
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Mar 16, 2001, 02:43 AM
 
I need to do intospection on class methods, rather than instances. I'm also using <objc/Object.h> rather than Cocoa.

Methods are there to check whether an *instance* responds to a message, but not for *classes*. Is there any way of doing this?

All words are lies. Including these ones.
     
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status: Offline
Reply With Quote
Mar 16, 2001, 08:34 AM
 
I'm really ignorant about these things (just getting started writing @interface etc files), but just to help get the ball rolling on this vital conversation...

I thought that I read that classes too can behave like instances of objects. Like you could send the class a message and such (for example, to ask it to create an object). So, if the capability is there to behave, what kind of calls are limited to instances and not classes?
Did you try just using the same method on the class? Or how about defining the method yourself in the class definition?

------------------
you are not your signature
you are not your signature
     
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
Mar 16, 2001, 10:27 AM
 
Any of the instance methods you see in NSObject.h (or Object.h) should be implemented by the class as well (i.e. they can also be used as class methods).

I.e., -respondsToSelector: if sent to an instance will tell you if there's an instance method for the selector, and if sent to a class will tell you if there's a class method for the selector. Same goes for methodForSelector:, methodSignatureForSelector:, etc. [This is respondsTo:, methodFor:, etc. if you're actually using the old objc/Object.h]
     
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Mar 16, 2001, 04:19 PM
 
A class does not behave, it is a table of code that describes the behavior and data of an object. Declaring an object asks the OS to create that object which is then immediately referred to the applicable constructor . The class doesn't "do" anything,it's just a list. The Object executes it's methods found in the class list and holds it's data in the prescribed manner.
     
Admin Emeritus
Join Date: Oct 2000
Location: Boston, MA
Status: Offline
Reply With Quote
Mar 16, 2001, 04:36 PM
 
A class does not behave
How so do you mean?
"Against stupidity, the gods themselves contend in vain" (Schiller)
     
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Mar 16, 2001, 06:30 PM
 
Very convienient editing of the quote, normal rules of grammar require a (...) if cutting a sentence short.

Parrallax - read the rest of my last post, epececially thr rest of the sentence you left out.

The Class Description is just that -a description. It has no life of it's own. An object instantiated of a particular class does have a life. It responds to messages, executes methods and can message other objects as described by the code in the class description.

If you dont believe me, here are your precious references:

Cox, Brad J., Object Oriented Programming -- An Evolutionary Approach ISBN 0-201-10393
(Yes, the same Brad Cox that did NeXT Openstep. Some have said this book was a preview to his work with NeXT-which led to Cocoa.)

Carrano, Helman and Verhoff., Wall and Mirrors Data abstraction and Problem Solving with C++. ISBN 0-201-87402-4
     
Admin Emeritus
Join Date: Oct 2000
Location: Boston, MA
Status: Offline
Reply With Quote
Mar 16, 2001, 07:28 PM
 
Classes can respond to messages to some degree.

A class object is created by the compiler to respond to messages (i.e. [NSBezierPath alloc]). So it does kind of have its own life. But we just say the class responds to it for short, and sometimes say "class" when we mean "class object."

Please don't take offense to my reply in the Gametes thread. I'm just having a bad day.

(BTW, it's parallax, not Parrallax. Thanks ;-)
"Against stupidity, the gods themselves contend in vain" (Schiller)
     
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status: Offline
Reply With Quote
Mar 16, 2001, 07:37 PM
 
I knew it! That class object stuff is exactly what I was saying; I remember it from ObjC.pdf. Now, can the class be set up to respond to questions about itse...hey wait. Isn't that why the class object is made by runtime in the first place? To answer questions from subclasses about methods and variables they contain?
you are not your signature
     
Mac Enthusiast
Join Date: Feb 2000
Location: Storrs,Connecticut, USA
Status: Offline
Reply With Quote
Mar 16, 2001, 07:55 PM
 
Originally posted by AirSluf:

The Class Description is just that -a description. It has no life of it's own. An object instantiated of a particular class does have a life. It responds to messages, executes methods and can message other objects as described by the code in the class description.

If you dont believe me, here are your precious references:

Cox, Brad J., Object Oriented Programming -- An Evolutionary Approach ISBN 0-201-10393
(Yes, the same Brad Cox that did NeXT Openstep. Some have said this book was a preview to his work with NeXT-which led to Cocoa.)

Carrano, Helman and Verhoff., Wall and Mirrors Data abstraction and Problem Solving with C++. ISBN 0-201-87402-4
Yea, great reference... a C++ reference. We are talking about Objective C here. in Objective C a class can have class methods which do not rely on the existence of an instance of a class. Now class methods don't use any instance variables, of course. usually class methods are just functions that are related to the class.

For example [NSSavePanel savePanel]; will return a pointer to the shared save panel in that program. If there is not already a save panel allocated it will allocate one. I believe that it retains it's tracking of the save panel using static variables, although I'm not sure. The point is that this is a class method, not an instance method. It has no access to instance variables. Objective C has class methods as a way to group functions that are very closely related to a class but could never be methods for an instance of that class. Another example is the + (void)strokeRectNSRect)aRect method in NSBezierPath. It draws a rectangle onto the screen using the default line width and the current color when you pass it a rectangle. It is appropriate for this method to be there because NSBezier path is where you go for most of your primitives. This is an example of where a class method is used to simplify grouping of stuff.

The moral is Objective C is not like C++. It's really different. C++ doesn't have autorelease and in objective C, like Java, you can't statically compile any of your classes.
     
Admin Emeritus
Join Date: Oct 2000
Location: Boston, MA
Status: Offline
Reply With Quote
Mar 16, 2001, 08:40 PM
 
Aye, the class object is created for several reasons. First, it makes perfect logical sense, and helps to generalize everything (but remember in ObjC.pdf, there is also a meta-class object). As Dalgo said, it's extremely useful to have those class methods for things like bezier paths or NSBundles. Otherwise you'd end up sending three messages (alloc, initialize, stroke). It would be an awful waste of memory and time.
"Against stupidity, the gods themselves contend in vain" (Schiller)
     
Senior User
Join Date: Nov 2000
Status: Offline
Reply With Quote
Mar 17, 2001, 02:24 AM
 
I think I see where your'e going.

It's more a semantics issue on my side, and I'm not using the same set of definitions as Dalgo and parallax. Yes, Curano uses C++ code as examples, but the object oriented discussions are language independent, and Cox talks Obj-C from chapter 3 on. None of it is in Cocoa, and I don't know any of Cocoa YET either (but I will over the next year or two). Sadies original question also says he is not using Cocoa.

I have been speaking from the definition side versus the coding in Cocoa side. With that in mind it sounds like the Classes you have been talking about are Abstract Base Classes or Virtual Classes. These have methods but are forbidden from ever having an object. The language dynamically binds the data type at run time to an object of a class derived from one of these classes depending on the context of the message. While it may look like you are accessing a class, the hidden Virtual Method Table created by the compiler acts as the traffic cop and routs things to the appropriate object. Dalgo, it looks like Cocoa nicely handles the catastrophic act of accessing an object that there are no instances of by creating one for you on the fly, reducing your programming overhead. It also looks like Cocoa naming conventions may not adhere exactly to the same conventions used in describing or constructing an Object-Oriented Language Set. Not the first or last time we will use the same words to describe something almost but not quite the same.

Everyone here seems very knowledgable about coding for the Mac, but Sadie needs to find out if his prof needs him to do his work using programming conventions as used in Cocoa or pure definitions for an Object-Oriented Language Set , vice a specific language.

g'night all. Good luck Sadie
     
Mac Enthusiast
Join Date: Feb 2000
Location: Storrs,Connecticut, USA
Status: Offline
Reply With Quote
Mar 17, 2001, 06:48 AM
 
Oh, here si the answer to sadie's question, straight from the NSObject documentation. Note that this works with class methods and not just instance methods like instancesRespondToSelector:

respondsToSelector:

- (BOOL)respondsToSelectorSEL)aSelector

Returns YES if the receiver implements or inherits a method that can respond to aSelector messages, NO otherwise. The application is responsible for determining whether a NO response should be considered an error.

Note that if the receiver is able to forward aSelector messages to another object, it will be able to respond to the message, albeit indirectly, even though this method returns NO.

See Also: - forwardInvocation: (NSObject class), + instancesRespondToSelector: (NSObject class)
     
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
Mar 17, 2001, 10:57 AM
 
Yes, a lot of this discussion is terminology confusion :-)

At this level, Objective-C and C++ are completely different languages. The details of message passing are totally different, and Objective-C has some constructs which really have no counterpart in C++ (class objects in particular). Most of Objective-C's features, syntax, and concepts are really derived from Smalltalk.

In Objective-C, an instance is an object, and a class is an object. Both instance and class methods than can be defined for a class, both kinds of methods are inherited from superclasses, and both kinds of methods can be overridden in subclasses. Messages sent to instances use the exact same mechanism as those sent to instances -- the runtime will simply look in the list of class methods instead of the list of instance methods.

For an example (code not compiled or tested):
Code:
#import <Foundation/Foundation.h> @interface MyClass : NSObject {/* no instance variables */ } + (void)foo; //class method foo - (void)foo; //instance method foo - (void)bar; //instance method bar @end @implementation MyClass + (void)foo { printf("Class Foo!\n"); } - (void)foo { printf("foo\n"); } - (void)bar { printf("bar\n"); } @end int main() { MyClass *myInstance = [[MyClass alloc] init]; SEL fooSelector = @selector(foo); SEL barSelector = @selector(bar); [myInstance respondsToSelector:fooSelector]; // YES [myInstance respondsToSelector:barSelector]; // YES [[myInstance class] respondsToSelector:fooSelector]; // YES [[myInstance class] respondsToSelector:barSelector]; // NO [MyClass respondsToSelector:fooSelector]; // YES [MyClass respondsToSelector:barSelector]; // NO [[myInstance class] instancesRespondToSelector:barSelector]; //YES [myInstance foo]; //prints "foo" [myInstance bar]; //prints "bar" [MyClass foo]; //prints "Class Foo!" [[myInstance class] foo] // prints "Class Foo!" }
To get into the low-level details of the ObjC runtime, every method call is transformed by the compiler into a call to the objc_msgSend() function, which takes the object being messaged, the name of the message (called the "selector"), plus any arguments the method may have. The first instance variable on any instance is "isa", a pointer to the class object. A class object has a defined structure, which you can see in objc/objc-class.h. objc_msgSend() dereferences the "isa", looks for the method corresponding to the selector, and when it is found the corresponding implementation is invoked (the function pointer for the implementation is part of the method structure). This lookup is really just a quick hashed lookup for speed (and the GNU runtime is even faster if I recall) but that's the general idea.

The first member of a class structure is also called "isa", and is a pointer to the meta-class. The meta-class is really just a companion class structure with all of the same stuff, except its list of methods contains all the class methods (the regular class object has the list of instance methods). Thus, when a class object is used with objc_msgSend(), class methods will be searched for instead of instance methods, but everything else is the same.

Object allocation uses this. ObjC has no special constructors; rather +alloc is a class method implemented on NSObject. All subclasses inherit that behavior, which is simply to allocate a new instance of the class. It is possible though for a subclass to override to change the behavior -- for example, a singleton class could override +alloc to make sure only one instance is ever created:

Code:
@implementation SingletonClass static SingletonClass *instance = nil; + (id)alloc { if (instance == nil) instance = [[super alloc] init]; return instance; } ... @end
[NB -- NSObject's +alloc method actually calls [self allocWithZone:] with the default memory zone, so in real life SingletonClass would override +allocWithZone: instead of +alloc.]

[Another note -- when the class name is "hard-coded", i.e. [MyClass respondsToSelector:someSelector], the runtime actually does a lookup with the string "MyClass" to find the associated class object, and objc_msgSend() is then called as normal.]

Most of the time class methods are involved with object creation, but they can be used to expose functionality related to a class that doesn't really need to create an instance (e.g. [NSDate timeIntervalSinceReferenceDate]), or to define other behavior on a class level.

For example, say we wanted to implement an inspector system, where a given object could have multiple inspectors. It could be done by having an abstract class called Inspector with many subclasses, with a couple methods define like:

Code:
@implementation Inspector + (BOOL)canInspectObject:(id)anObject { return NO; } + (NSString *)displayString { return @"?????"; } ... @end
Each inspector subclass would then override +canInspectObject: to decide whether or not the inspector class can inspect the given object, and override +displayString to return a suitable description.

The act of finding the inspectors for an object could then be done like:

Code:
- (void)displayInspectorsForObject:(id)anObject { // assume allInspectorClasses exists -- contains all of the class // objects for Inspector subclasses, which can be done with runtime // introspection NSArray *allInspectorClasses; NSMutableArray *chosenInspectorClasses = [NSMutableArray array]; NSMutableArray *inspectorStrings = [NSMutableArray array]; int i; int count; count = [allInspectorClasses count]; for (i=0; i<count; i++) { Class inspectorClass = [allInspectorClasses objectAtIndex:i]; if ([inspectorClass canInspectObject:anObject]) { [chosenInspectorClasses addObject:inspectorClass]; [inspectorStrings addObject:[inspectorClass displayString]]; } } // At this point, display the list of strings, say in a popup list [popupButton removeAllItems]; [popupButton addItemsWithTitles:inspectorStrings]; // Store chosen inspectors in an ivar [self setCurrentInspectorClasses:chosenInspectorClasses]; } // this method is the NSPopUpButton target - (void)popupItemChosen:(id)sender { int chosenIndex = [popupButton indexOfSelectedItem]; Class chosenClass = [[self currentInspectorClasses] objectAtIndex:chosenIndex]; Inspector *inspector = [[chosenClass alloc] init]; //or a shared instance maybe // now do whatever you like with the Inspector instance -- most // likely swapping in the associated NSView into the inspector // panel }
An approach like the above lets the inspector-choosing mechanism stay completely generic, with the various Inspector subclasses deciding for themselves whether they are applicable or not. This way, the act of adding a new inspector can be done simply by implementing a new Inspector subclass and compiling it in (thus adding the class to the runtime). The generic code doesn't have to change. Furthermore, instances of the inspectors don't have to be created until they are actually needed.

Sorry this went on so long, but hopefully it helped :-)

In sadie's case, using <objc/Object.h> simply means a different class library is being used, but the Objective-C language is still the same. [Object was the old common superclass, before NeXT switched to NSObject several years ago. Cocoa is really a class library, and all of its classes are based around NSObject. NSObject implementations are available from Apple and GNUSTEP, whereas Object comes as part of the gcc compiler and is therefore available on more systems -- this is presumably why sadie wanted to inherit from Object instead of NSObject.
     
sadie  (op)
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Mar 17, 2001, 05:14 PM
 
Thank! That answers my question, as well as a few others (including 'How easy is it to start a religious war?').

What i need to know now is: what's the best way of making a selector? I have the name of the method in a C string (char*) and I know the arguments from elsewhere. @selector(foo: ) only works if you know the name of the selector at compile-time, not at runtime.

And remember, I'm using the old <objc/Object.h>, not Cocoa, so NSGreatSelectorMakerMethod is out



ps - if anyone knows the C structure that gets typedef'd into SEL, i'd happily edit it by hand!

[This message has been edited by sadie (edited 03-17-2001).]
All words are lies. Including these ones.
     
sadie  (op)
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Mar 17, 2001, 05:36 PM
 
Lindberg coded:
@implementation SingletonClass
static SingletonClass *instance = nil;
+ (id)alloc ...
@end
Hold it - that works???? You can make private, static variables? Since when? None of the documentation mentions that!

All words are lies. Including these ones.
     
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
Mar 17, 2001, 11:30 PM
 
Originally posted by sadie:
What i need to know now is: what's the best way of making a selector? I have the name of the method in a C string (char*) and I know the arguments from elsewhere. @selector(foo: ) only works if you know the name of the selector at compile-time, not at runtime.
NSSelectorFromString()

And remember, I'm using the old <objc/Object.h>, not Cocoa, so NSGreatSelectorMakerMethod is out
Oh, right :-)

sel_getUid(). That may be sel_get_uid() on non-Apple systems.

ps - if anyone knows the C structure that gets typedef'd into SEL, i'd happily edit it by hand!
It's private. I'm pretty sure that under the Apple implementation there's not really a structure -- a SEL is really a specially uniqued c-string. In the GNU implementation it really is a structure though. In the end, just use the functions and you'll be fine :-)



static SingletonClass *instance = nil;

Hold it - that works???? You can make private, static variables? Since when? None of the documentation mentions that!
Static variables are a part of ANSI C (and therefore part of Objective-C). They are global variables -- NOT instance variables -- but their scope is limited to the source code file they're in, and the names will not conflict with static variables of the same name in other files.
     
sadie  (op)
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Mar 18, 2001, 03:33 AM
 
Thanks, lindberg. Now how do i encode the arguments in the string? Is it enough just to turn the name "echo" with two arguments into "echo::"? Or does it matter that the - echo; method really says "echo:with:"?

All words are lies. Including these ones.
     
sadie  (op)
Senior User
Join Date: Feb 2001
Location: Rochester, uk
Status: Offline
Reply With Quote
Mar 18, 2001, 05:03 AM
 
Hey, everyone. Can i just point out one little thing?

YES! IT WORKS! IT SMEGGING WORKS!

Thank you. Especially lindberg, you've been great.

All words are lies. Including these ones.
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 09:42 AM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2