Defining categories for protocols in Objective-C?

后端 未结 7 917
走了就别回头了
走了就别回头了 2020-12-02 10:39

In Objective-C, I can add methods to existing classes with a category, e.g.

@interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
@end
         


        
7条回答
  •  半阙折子戏
    2020-12-02 11:14

    While it's true that you can't define categories for protocols (and wouldn't want to, because you don't know anything about the existing object), you can define categories in such a way that the code only applies to an object of the given type that has the desired protocol (sort of like C++'s partial template specialization).

    The main use for something like this is when you wish to define a category that depends on a customized version of a class. (Imagine that I have UIViewController subclasses that conform to the Foo protocol, meaning they have the foo property, my category code may have need of the foo property, but I can't apply it to the Foo protocol, and if I simply apply it to UIViewController, the code won't compile by default, and forcing it to compile means someone doing introspection, or just screwing up, might call your code which depends on the protocol. A hybrid approach could work like this:

    @protocol Foo
    - (void)fooMethod
    
    @property (retain) NSString *foo;
    @end
    
    @implementation UIViewController (FooCategory)
    
    - (void)fooMethod {
        if (![self conformsToProtocol:@protocol(Foo)]) {
            return;
        }
    
        UIViewController *me = (UIViewController*) self;
        // For the rest of the method, use "me" instead of "self"
        NSLog(@"My foo property is \"%@\"", me.foo);
    }
    @end
    

    With the hybrid approach, you can write the code only once (per class that is supposed to implement the protocol) and be sure that it won't affect instances of the class that don't conform to the protocol.

    The downside is that property synthesis/definition still has to happen in the individual subclasses.

提交回复
热议问题