Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -376,10 +376,37 @@ * \return The old implementation */ + (IMP)replaceInstanceMethod: (SEL)selector withMethodFromClass: (Class)class_; +/** + * \brief Adds an instance method to the class. + * + * If the method already exists, nothing is done and NO is returned. If you want + * to change the implementation of a method, use + * setImplementation:forInstanceMethod:. + * + * \param selector The selector for the new method + * \param typeEncoding The type encoding for the new method + * \param implementation The implementation for the new method + * \return Whether the method has been added + */ ++ (BOOL)addInstanceMethod: (SEL)selector + withTypeEncoding: (const char*)typeEncoding + implementation: (IMP)implementation; + +/** + * \brief Adds all instance methods from the specified class to the class that + * is the receiver. + * + * Existing methods will not be overriden, so that it behaves similar to normal + * inheritance. + * + * \param class The class from which the instance methods should be inherited + */ ++ (void)inheritInstanceMethodsFromClass: (Class)class; + /** * \brief Initializes an already allocated object. * * Derived classes may override this, but need to do self = [super init] before * they do any initialization themselves. init may never return nil, instead Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -25,10 +25,12 @@ #include #include #import "OFObject.h" +#import "OFArray.h" +#import "OFIntrospection.h" #import "OFAutoreleasePool.h" #import "OFAllocFailedException.h" #import "OFEnumerationMutationException.h" #import "OFInitializationFailedException.h" @@ -445,10 +447,48 @@ newImp = [class instanceMethodForSelector: selector]; return [self setImplementation: newImp forInstanceMethod: selector]; } + ++ (BOOL)addInstanceMethod: (SEL)selector + withTypeEncoding: (const char*)typeEncoding + implementation: (IMP)implementation +{ +#if defined(OF_APPLE_RUNTIME) || defined(OF_GNU_RUNTIME) + return class_addMethod(self, selector, implementation, typeEncoding); +#elif defined(OF_OLD_GNU_RUNTIME) + @throw [OFNotImplementedException newWithClass: isa + selector: _cmd]; +#endif +} + ++ (void)inheritInstanceMethodsFromClass: (Class)class +{ + OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; + OFIntrospection *introspection; + OFMethod **cArray; + size_t i, count; + + introspection = [OFIntrospection introspectionWithClass: class]; + cArray = [[introspection instanceMethods] cArray]; + count = [[introspection instanceMethods] count]; + + for (i = 0; i < count; i++) { + SEL selector; + IMP implementation; + + selector = [cArray[i] selector]; + implementation = [class instanceMethodForSelector: selector]; + + [self addInstanceMethod: selector + withTypeEncoding: [cArray[i] typeEncoding] + implementation: implementation]; + } + + [pool release]; +} - init { return self; }