Is there any way to discover at runtime which subclasses exist of a given class?
Edit: From the answers so far I think I need to clarify a bit more what I am trying to do. I am aware that this is not a common practice in Cocoa, and that it may come with some caveats.
I am writing a parser using the dynamic creation pattern. (See the book Cocoa Design Patterns by Buck and Yacktman, chapter 5.) Basically, the parser instance processes a stack, and instantiates objects that know how to perform certain calculations.
If I can get all the subclasses of the MYCommand
class, I can, for example, provide the user with a list of available commands. Also, in the example from chapter 5, the parser has an substitution dictionary so operators like +, -, * and / can be used. (They are mapped to MYAddCommand
, etc.) To me it seemed this information belonged in the MyCommand
subclass, not the parser instance as it kinda defeats the idea of dynamic creation.
Not directly, no. You can however get a list of all classes registered with the runtime as well as query those classes for their direct superclass. Keep in mind that this doesn't allow you to find all ancestors for the class up the inheritance tree, just the immediate superclass.
You can use objc_getClassList()
to get the list of Class
objects registered with the runtime. Then you can loop over that array and call [NSObject superclass]
on those Class
objects to get their superclass' Class
object. If for some reason your classes do not use NSObject
as their root class, you can use class_getSuperclass()
instead.
I should mention as well that you might be thinking about your application's design incorrectly if you feel it is necessary to do this kind of discovery. Most likely there is another, more conventional way to do what you are trying to accomplish that doesn't involve introspecting on the Objective-C runtime.
Rather than try to automatically register all the subclasses of MYCommand
, why not split the problem in two?
First, provide API for registering a class, something like +[MYCommand registerClass:]
.
Then, create code in MYCommand that means any subclasses will automatically register themselves. Something like:
@implementation MYCommand
+ (void)load
{
[MYCommand registerClass:self];
}
@end
Marc and bbum hit it on the money. This is usually not a good idea.
However, we have code on our CocoaHeads wiki that does this: http://cocoaheads.byu.edu/wiki/getting-all-subclasses
Another approach was just published by Matt Gallagher on his blog.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With