objective-c - 为什么 "conformsToProtocol"不检查 "required"方法实现?

标签 objective-c class methods protocols

我正在尝试执行“正式的”@protocol,但无法可靠地测试我的类/实例是否确实实现了协议(protocol)的“必需”方法,而不是简单地“声明”他们符合协议(protocol)。

我的困境的一个完整例子......

#import <Foundation/Foundation.h>

@protocol       RequiredProtocol 
@required                   
- (NSString*) mustImplement;                              @end 
@interface      Cog         : NSObject <RequiredProtocol> @end
@implementation Cog                                       @end
@interface      Sprocket    : NSObject                    @end 
@implementation Sprocket 
- (NSString*) mustImplement
  { return @"I conform, but ObjC doesn't care!"; }        @end

int main(int argc, char *argv[]) {

    Protocol *required = @protocol(RequiredProtocol);
    SEL    requiredSEL = @selector(mustImplement);
    void (^testProtocolConformance)(NSObject*) = ^(NSObject *x){
        NSLog(@"Protocol:%@\n"
               "Does %@ class conform:%@     \n"
               "Do  instances conform:%@     \n"
               "Required method's result:\"%@\"", 
        NSStringFromProtocol ( required ),
        NSStringFromClass    ( x.class  ), 
        [x.class conformsToProtocol:required] ? @"YES" : @"NO", 
        [x       conformsToProtocol:required] ? @"YES" : @"NO",
        [x    respondsToSelector:requiredSEL] ? [x mustImplement]
                                              : nil );
    };
    testProtocolConformance ( Cog.new      );
    testProtocolConformance ( Sprocket.new );
}

结果:

Protocol:RequiredProtocol
Does Cog class conform:YES
Do instances conform:YES
Required method's result:"(null)"

Protocol:RequiredProtocol
Does Sprocket class conform:NO
Do instances conform:NO
Required method's result:"I conform, but ObjC doesn't care!"

为什么一个类及其实例确实实现了 @protocol 的方法 (Sprocket) 返回 NOconformsToProtocol?

为什么实际上不符合,但说它符合 (Cog) 返回 YES

如果只需要声明就可以假装符合,那么正式协议(protocol)还有什么意义呢?

如何在不多次调用 respondsToSelector 的情况下实际检查多个 @selector 的完整实现?

@Josh Caswell.. 没有 diff 两者.. 我猜你的响应达到了与我一直在使用的 NSObject 上的类别相似的效果同时……

@implementation NSObject (ProtocolConformance)
- (BOOL) implementsProtocol:(id)nameOrProtocol {
   Protocol *p = [nameOrProtocol isKindOfClass:NSString.class] 
               ? NSProtocolFromString(nameOrProtocol) 
               : nameOrProtocol;  // Arg is string OR protocol
   Class klass = self.class;
   unsigned int outCount = 0;
   struct objc_method_description *methods = NULL;
   methods = protocol_copyMethodDescriptionList( p, YES, YES, &outCount);
   for (unsigned int i = 0; i < outCount; ++i) {
       SEL selector = methods[i].name;
       if (![klass instancesRespondToSelector: selector]) {
           if (methods) free(methods); methods = NULL; return NO;
       }
    }
    if (methods) free(methods); methods = NULL; return YES;
}
@end

最佳答案

遵守协议(protocol)只是一个“ promise ”,您无法知道conformsToProtocol: 的接收者是否真的实现了所有需要的方法。使用尖括号语法声明该类符合协议(protocol)就足够了,conformsToProtocol: 将返回 yes:

Discussion
A class is said to “conform to” a protocol if it adopts the protocol or inherits from another class that adopts it. Protocols are adopted by listing them within angle brackets after the interface declaration.

完整来源:NSObject's conformsToProtocol: .

协议(protocol)声明的优势在于您可以在编译时知道一个类是否真的采用了所需的方法。如果没有,将发出警告。我建议不要依赖conformsToProtocol:,而是使用内省(introspection)。也就是说,通过调用 instancesRespondToSelector:/respondsToSelector: 来验证一个类/对象是否实现了一个方法:

+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
- (BOOL)respondsToSelector:(SEL)aSelector;

关于objective-c - 为什么 "conformsToProtocol"不检查 "required"方法实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16820466/

相关文章:

ios - 如何获得相对于 ScrollView super View 的 ScrollView subview 的中心点?

java - 如何确保同步覆盖的方法

c++ - 将指针类方法作为参数传递给另一个类方法 C++

java - 向时钟添加时间(不起作用)-JAVA

javascript - 这个数组过滤器中的函数是如何工作的?

ios - 快速持续声明

ios - 无法在 ios 中使用带有自定义按钮的 api v2.4 登录 facebook

ios - 在 iOS7 的 viewWillDisappear 期间不再能够隐藏键盘

c++ - 为方法提供一个空实例是一种好习惯吗?

c++ - 甚至在创建该类之前声明一个对象