Re: [Pyobjc-dev] Access to 'hidden' class-methods
Brought to you by:
ronaldoussoren
From: <bb...@ma...> - 2003-01-13 16:25:52
|
On Sunday, Jan 12, 2003, at 16:53 US/Eastern, Ronald Oussoren wrote: >> Hmm, another wild idea: would this mean that by declaring a category >> on the metaclass you could influence creation of all ObjC objects? > You probably could, but: the metaclass has the same name as the normal > class which makes it hard to define a category on it. But is guess > defining a category containing class-mehods on a normal class would do > what you want. Adding methods to a class via a category works just like instance methods; the methods will be added and all of the inheritance based method dispatch rules will be followed. You can add methods in a category to NSObject to influence all classes rooted at NSObject (ObjC does not require you to use NSObject as the root class or even have a superclasss at all). Keep in mind that categories that override existing functionality are generally evil in any context but in an application-- even then, they are dangerous. Overriding existing functionality means that you are changing the behavior of the overridden API in a fashion where people using that API have no way of accessing the original functionality. -- Posing allows one to access the original implementation. That is, I could override NSObject's -description (or +description) method in a subclass, tell that subclass to pose as NSObject, and my functionality would override NSObject's implementation. Unlike categories, I could still invoke the original implementation by calling [super description] in my description method. -- Method swizzling involves directly editing the objective-c runtime to change the behavior of an existing object. A very handy tool. For example, if the following class is loaded into an application, it will cause NSUserDefaults to print every default and its value as the application accesses the defaults: @interface NoisyDefaults:NSUserDefaults @end @implementation NoisyDefaults static IMP ofk; id objectForKey(self, _cmd, defaultName) { id v = ofk(self, _cmd, defaultName); fprintf(stdout, "%s ==> %s\n", [defaultName cString], [[v description] cString]); return v; } +(void) load { Method origM; origM = class_getInstanceMethod([NSUserDefaults class], @selector(objectForKey:)); ofk = origM->method_imp; origM->method_imp = objectForKey; } @end Swizzling is a handy debugging tool, but should be avoided in real world situations. -- ObjC also provides lower level tools for manipulating the behavior of the runtime. PyObjC uses these APIs to build classes on the fly (and-- someday-- categories, too). OBJC_EXPORT void objc_setClassHandler(int (*)(const char *)); /* overriding the default object allocation and error handling routines */ OBJC_EXPORT id (*_alloc)(Class, unsigned int); OBJC_EXPORT id (*_copy)(id, unsigned int); OBJC_EXPORT id (*_realloc)(id, unsigned int); OBJC_EXPORT id (*_dealloc)(id); OBJC_EXPORT id (*_zoneAlloc)(Class, unsigned int, void *); OBJC_EXPORT id (*_zoneRealloc)(id, unsigned int, void *); OBJC_EXPORT id (*_zoneCopy)(id, unsigned int, void *); OBJC_EXPORT void (*_error)(id, const char *, va_list); |