Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
193 views
in Technique[技术] by (71.8m points)

ios - Override a method in Objective c via category

The following is working in objective c:

// Base Class in ClassA.h and ClassA.m
@interface ClassA : NSObject 
- (NSString *) myMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
@end

//Category in ClassA+CategoryB.h and ClassA+CategoryB.m
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

The question is, if I am just importing ClassA.h and send the message

[myClassA myMethod]; //returns B

why is this returning B? I am not importing ClassA+CategoryB

Even futhrer, if I did the following:

// Base Class in ClassA.h and ClassA.m
@interface ClassA : NSObject 
- (NSString *) myMethod;
- (NSString *) mySecondMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
- (NSString *) mySecondMethod { return [self myMethod]; }
@end

//Category in ClassA+CategoryB.h and ClassA+CategoryB.m
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

and call mySecondMethod:

ClassA *a = [[ClassA alloc] init];
NSLog(@"%@",[a myMethod]);

the result will still be B although nobody knows (due to no import) of the category implementation?!

I'd excepted, only to return Bif I was importing the category...

So any hints appreciated.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Objective-C messaging is dynamic, this means that it doesn't matter if you import or not the category. The object will receive the message and execute that method.

The category is overriding your method. This means that when the runtime sends a message to that object, will always find the overridden method, no matter what you import.

If you want to ignore a category you shouldn't compile it, so you could remove the category from the compiler sources.
An alternative is subclassing.

Also read this:

Avoid Category Method Name Clashes

Because the methods declared in a category are added to an existing class, you need to be very careful about method names.

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.

So in your case you haven't got any problem because as stated, this is less likely to happen with user defined classes. But you should definitely use subclassing instead of writing a category.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...