2011-11-06 5 views
7

En Objective C, conocer los protocolos pueden ser obligatorios u opcionales:protocolos Objective C que requieren la aplicación de al menos uno de un conjunto de métodos

@protocol AProtocol 

@required 
-(void) aRequiredMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

¿Hay una manera elegante de decir que el objeto cumpla con el protocolo ha de responder a por lo menos uno de un conjunto de métodos, mi sueño sería algo así como

@protocol AProtocol 

@anyof 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@optional 
-(void) anOptionalMethod; 

@end 

EDIT:

Este ser (por lo que yo sé), imposible, que está ld no sea una manera de criar a un tiempo de compilación de advertencia si una clase declarada conforme a un protocolo dado hecha de métodos opcionales

@protocol AProtocol 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 

@end 

No se pudo implementar al menos uno de ellos.

+0

re: 'EDIT' que no he visto. Si realmente desea automatizar esto, puede usar el tiempo de ejecución objc. – justin

Respuesta

3

No es una gran manera de expresar esto en Objective-C. Si debe hacer esto, la OMI es la forma más idiomática y menos desagradable de código en este sentido:

@protocol AProtocol 

@required 
- (SEL)methodToUse; // returns one of "onePossibleMethod" or "anotherPossibleMethod" 

@optional 
-(void) onePossibleMethod; 
-(void) anotherPossibleMethod; 
-(void) anOptionalMethod; 

@en 
+0

Estoy de acuerdo en que no hay una buena manera, pero me gusta su solución porque la convierte en "oficial" (es decir, distinta de los comentarios/documentación) para los desarrolladores que no están familiarizados con el código, aunque los tres métodos son opcionales. ellos para ser implementados. – jbat100

0

Puede tener una propiedad delegada dinámica que solo permita que el delegado se asigne a las clases que implementan un método u otro, pero que estaría en tiempo de ejecución y no en tiempo de compilación. También puede crear un script bash que verifique si se implementó uno u otro y que estaría en tiempo de compilación.

3

Bueno, ya están trabajando con ObjC, por lo que tendrá que ejercer cierta moderación mismo:

@protocol MONAbstractDataProvider 
@optional 
- (void)anOptionalMethod; 
@end 

@protocol MONDataProviderA <MONAbstractProvider> 
@required 
- (void)onePossibleMethod; 
@end 

@protocol MONDataProviderB <MONAbstractProvider> 
@required 
- (void)anotherPossibleMethod; 
@end 

En ese caso, tendrá que hacer una prueba confromsToProtocol: en el callsite, en lugar de la prueba respondsToSelector: para onePossibleMethod y anotherPossibleMethod. Luego pasas MONAbstractDataProvider alrededor. Eso puede introducir algún tipo de seguridad, siempre que recuerde las reglas, pero en realidad es solo un poco mejor que el enfoque habitual.

De modo que el lado del cliente se vería así:

- (void)update:(NSObject<MONAbstractDataProvider>*)provider 
{ 
    if ([provider conformsToProtocol:@protocol(MONDataProviderA)]) { 
     [(NSObject<MONDataProviderA>*)protocol onePossibleMethod]; 
    } 
    else if ([provider conformsToProtocol:@protocol(MONDataProviderB)]) { 
     [(NSObject<MONDataProviderB>*)provider anotherPossibleMethod]; 
    } 
    else { 
     assert(0 && "rule broken"); 
    } 
} 

Eso, por supuesto, supone que el cliente sabe acerca de todos los derivados.

su lugar, puede prefiere el enfoque singular simple si ambos son void:

@protocol MONAbstractDataProvider 
@required 
- (void)performPossibleMethod; 
@optional 
- (void)anOptionalMethod; 
@end 
+0

gracias por su respuesta detallada, esta sería una forma de hacer el control en tiempo de ejecución. Idealmente, lo que me gustaría es algún tipo de verificación en tiempo de compilación que genere una advertencia (edité la pregunta un poco). – jbat100

+0

@ jbat100 hmm - no hice los detalles del enfoque muy claros. la verificación del tiempo de compilación entra porque 'MONAbstractDataProvider' solo se adopta * indirectamente *. las clases solo deberían adoptar 'MONDataProviderA' o' MONDataProviderB', nunca 'MONAbstractDataProvider' directamente. – justin

Cuestiones relacionadas