如何为Objective-C协议提供默认实现?

fbr*_*eto 22 protocols objective-c standards-compliance default-implementation overhead-minimization

我想指定一个带有可选例程的Objective-C协议.当例程没有由符合协议的类实现时,我想在其位置使用默认实现.协议本身是否存在我可以定义此默认实现的位置?如果没有,减少复制和粘贴此默认实现的最佳做法是什么?

Rya*_*yan 19

Objective-C协议没有默认实现的可供性.它们纯粹是方法声明的集合,可以由其他类实现.Objective-C中的标准做法是在运行时测试一个对象,看它是否在调用该方法之前响应给定的选择器,使用 - [NSObject respondsToSelector:].如果e对象没有响应给定的选择器,则不调用该方法.

实现所需结果的一种方法是定义一个封装您在调用类中查找的默认行为的方法,如果该对象未通过测试,则调用该方法.

另一种方法是在协议中使用该方法,并在您可能不想提供特定实现的任何类的超类中提供默认实现.

可能还有其他选项,但一般来说,在Objective-C中没有特定的标准实践,除非根据上面的第一段,如果它没有被对象实现,可能只是不调用给定的方法. .


w-m*_*w-m 17

没有标准的方法可以做到这一点,因为协议不应该定义任何实现.

由于Objective-C带有一个整洁的运行时,你当然可以添加这样的行为,如果你真的认为你需要这样做(并且不可能通过继承实现相同).

假设您声明了MyProtocol,那么只需在协议声明下的.h文件中添加一个具有相同名称的接口:

@interface MyProtocol : NSObject <MyProtocol>

+ (void)addDefaultImplementationForClass:(Class)conformingClass;

@end
Run Code Online (Sandbox Code Playgroud)

并创建一个相应的实现文件(在这里使用MAObjCRuntime以获取可读性,但标准运行时函数不会有更多代码):

@implementation MyProtocol

+ (void)addDefaultImplementationForClass:(Class)conformingClass {
  RTProtocol *protocol = [RTProtocol protocolWithName:@"MyProtocol"];
  // get all optional instance methods
  NSArray *optionalMethods = [protocol methodsRequired:NO instance:YES];
  for (RTMethod *method in optionalMethods) {
    if (![conformingClass rt_methodForSelector:[method selector]]) {
      RTMethod *myMethod = [self rt_methodForSelector:[method selector]];
      // add the default implementation from this class
      [conformingClass rt_addMethod:myMethod];
    }
  }
}

- (void)someOptionalProtocolMethod {
  // default implementation
  // will be added to any class that calls addDefault...: on itself
}
Run Code Online (Sandbox Code Playgroud)

然后你只需要打电话

[MyProtocol addDefaultImplementationForClass:[self class]];
Run Code Online (Sandbox Code Playgroud)

在符合协议的类的初始化程序中,将添加所有默认方法.