Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -393,22 +393,27 @@ + (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. + * \brief Adds all methods from the specified class to the class that is the + * receiver. * * Methods implemented by the receiving class itself will not be overridden, * however methods implemented by its superclass will. Therefore it behaves * similar as if the specified class is the superclass of the receiver. + * + * All methods from the superclasses of the specified class will also be added. + * + * If the specified class is a superclass of the receiving class, nothing is + * done. * * The specified class may not use instance variables and has to use accessors. * * \param class The class from which the instance methods should be inherited */ -+ (void)inheritInstanceMethodsFromClass: (Class)class; ++ (void)inheritMethodsFromClass: (Class)class; /** * \brief Initializes an already allocated object. * * Derived classes may override this, but need to do self = [super init] before Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -474,49 +474,89 @@ @throw [OFNotImplementedException newWithClass: self selector: _cmd]; #endif } -+ (void)inheritInstanceMethodsFromClass: (Class)class ++ (void)inheritMethodsFromClass: (Class)class { - OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFMutableSet *set = [OFMutableSet set]; + OFAutoreleasePool *pool; + OFMutableSet *classMethods, *instanceMethods; OFIntrospection *introspection; OFMethod **cArray; size_t i, count; + if ([self isSubclassOfClass: class]) + return; + + pool = [[OFAutoreleasePool alloc] init]; + + classMethods = [OFMutableSet set]; + instanceMethods = [OFMutableSet set]; + introspection = [OFIntrospection introspectionWithClass: self]; + + cArray = [[introspection classMethods] cArray]; + count = [[introspection classMethods] count]; + + for (i = 0; i < count; i++) + [classMethods addObject: [cArray[i] name]]; + cArray = [[introspection instanceMethods] cArray]; count = [[introspection instanceMethods] count]; for (i = 0; i < count; i++) - [set addObject: [cArray[i] name]]; + [instanceMethods addObject: [cArray[i] name]]; introspection = [OFIntrospection introspectionWithClass: class]; + + cArray = [[introspection classMethods] cArray]; + count = [[introspection classMethods] count]; + + for (i = 0; i < count; i++) { + SEL selector; + IMP implementation; + + if ([classMethods containsObject: [cArray[i] name]]) + continue; + + selector = [cArray[i] selector]; + implementation = [class methodForSelector: selector]; + + if ([self respondsToSelector: selector]) + [self setImplementation: implementation + forClassMethod: selector]; + else + [self addClassMethod: selector + withTypeEncoding: [cArray[i] typeEncoding] + implementation: implementation]; + } + cArray = [[introspection instanceMethods] cArray]; count = [[introspection instanceMethods] count]; for (i = 0; i < count; i++) { SEL selector; IMP implementation; - if ([set containsObject: [cArray[i] name]]) + if ([instanceMethods containsObject: [cArray[i] name]]) continue; selector = [cArray[i] selector]; implementation = [class instanceMethodForSelector: selector]; - if ([self respondsToSelector: selector]) + if ([self instancesRespondToSelector: selector]) [self setImplementation: implementation forInstanceMethod: selector]; else [self addInstanceMethod: selector withTypeEncoding: [cArray[i] typeEncoding] implementation: implementation]; } [pool release]; + + [self inheritMethodsFromClass: [class superclass]]; } - init { return self;