为什么“遵循协议”不检查“所需”方法实现? [英] Why does "conformsToProtocol" not check for "required" method implementations?

查看:120
本文介绍了为什么“遵循协议”不检查“所需”方法实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图强制执行一个正式 @protocol ,但不能可靠地测试我的类/实例是否实际执行协议的必需方法,vs



一个完整的例子。

  #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,但ObjC不在乎! } @end

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

协议*必需= @protocol(RequiredProtocol);
SEL requiredSEL = @selector(mustImplement);
void(^ testProtocolConformance)(NSObject *)= ^(NSObject * x){
NSLog(@Protocol:%@ \\\

%@ class conform:%@ \\\

实例符合:%@ \\\

必需方法的结果:\%@ \,
NSStringFromProtocol(必需),
NSStringFromClass(x.class),
[x.class conformsToProtocol:required]?@YES:@NO,
[x conformsToProtocol:required]?@YES:@NO ,
[x respondingToSelector:requiredSEL]?[x必须实现]
:nil);
};
testProtocolConformance(Cog.new);
testProtocolConformance(Sprocket.new);
}

结果:

 协议:RequiredProtocol 
Cog类是否符合:YES
实例符合:YES
必需方法的结果:(null)

协议:RequiredProtocol
Sprocket类是否符合:NO
实例符合:NO
必需的方法的结果:I conform,but ObjC does not care!

为什么一个类和它的实例实现 @protocol 的方法( Sprocket )return NO conformsToProtocol



为什么一个不符合,但SAYS认为它( Cog )return YES



如果声明完全符合一致性,那么正式协议的要点是什么?



如何实现检查多个 @selector 的完整实现,而不需要MULTIPLE调用 responsesToSelector



@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 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


解决方案

符合协议只是一个promise,你不能知道 conformsToProtocol:的接收器是否实际上实现了所有需要的方法。只要使用尖括号语法声明该类符合协议就足够了, conformsToProtocol:将返回yes:


讨论

如果一个类采用协议或者继承自另一个采用协议的类,它被称为符合一个协议。协议通过在接口声明后的尖括号中列出。


完整来源: NSObject's conformsToProtocol: 。 / p>

协议声明具有的优点是,如果类真的采用所需的方法,您可以在编译时知道 。如果不是,将给出警告。我建议不要依赖 conformsToProtocol:,而是使用内省。也就是说,通过调用 instancesRespondToSelector: / responsesToSelector:,验证类/对象是否实现了方法:

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


I am trying to enforce a "formal" @protocol, but cannot reliably test my classes/instances as to whether they ACTUALLY implement the protocol's "required" methods, vs. simply "declaring" that they conform to the protocol.

A complete example of my quandary…

#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 );
}

Result:

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!"

Why is it that a class and it's instances that DO implement the @protocol's methods (Sprocket) return NO to conformsToProtocol?

And why does one that DOESN'T ACTUALLY conform, but SAYS that it DOES (Cog) return YES?

What is the point of a formal protocol if the declaration is all that's needed to feign conformance?

How can you ACTUALLY check for complete implementation of multiple @selectors without MULTIPLE calls to respondsToSelector?

@Josh Caswell.. Without diffing the two.. I'd guess that your response achieves similar effect to the category on NSObject I've been using in the meantime…

@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

解决方案

Conforming to a protocol is just a "promise", you can't know if the receiver of conformsToProtocol: actually implements all the required methods. Is enough that you declare that the class conforms to the protocol using the angle brackets syntax, and conformsToProtocol: will return 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.

Full source: NSObject's conformsToProtocol: .

Protocols declarations have just the advantage that you can know at compile time if a class really adopts that required methods. If not, a warning will be given. I suggest to don't rely on conformsToProtocol:, but to use introspection instead. That is, verify if a class/object implements a method by calling instancesRespondToSelector: / respondsToSelector: :

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

这篇关于为什么“遵循协议”不检查“所需”方法实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆