2011-09-22 10 views

Respuesta

22

Es simplemente el mismo concepto que la herencia de clases. Si un protocolo adopta otro protocolo, "hereda" los métodos declarados de este protocolo adoptado. El protocolo NSObject declara especialmente métodos como respondsToSelector:. Por lo tanto, esto es especialmente útil si declara un @protocol que tiene métodos @optional, porque cuando llame a métodos en objetos que cumplen este protocolo, deberá verificar si el objeto responde al método antes de llamarlo si este método es opcional.


@protocol SomeProtocol <NSObject> 
-(void)requiredMethod; 
@optional 
-(void)optionalMethod; 
@end 

@interface SomeObject : NSObject 
-(void)testMyDelegate; 
@property(nonatomic, assign) id<SomeProtocol> myDelegate; 
@end 

@implementation SomeObject 
@synthesize myDelegate 

-(void)testMyDelegate { 
    // Here you can call requiredMethod without any checking because it is a required (non-optional) method 
    [self.myDelegate requiredMethod]; 

    // But as "optionalMethod" is @optional, you have to check if myDelegate implements this method before calling it! 
    if ([myDelegate respondsToSelector:@selector(optionalMethod)]) { 
     // And only call it if it is implemented by the receiver 
     [myDelegate optionalMethod]; 
    } 
} 
@end 

Usted sólo será capaz de llamar respondsToSelector en myDelegate si myDelegate se declara como un tipo que implementa respondsToSelector (de lo contrario tendrá algunas advertencias). Es por eso que el protocolo <SomeProtocol> necesita adoptar el protocolo <NSObject>, que a su vez declara este método.

Es posible pensar en id<SomeProtocol> como "cualquier objeto, sea cual sea su tipo (id), sólo tiene que poner en práctica los métodos declarados en SomeProtocol, incluyendo los métodos declarados en el protocolo padres NSObject. Así que puede ser un objeto de cualquier tipo, pero porque SomeProtocol adopta el protocolo NSObject sí, se garantiza que se le permite llamar respondsToSelector en este objeto, lo que permite comprobar si el objeto implementa un método dado antes de llamar a él si es opcional.


Tenga en cuenta que tampoco puede hacer que SomeProtocol adopte el protocolo NSObject y en su lugar declare su variable como id<SomeProtocol,NSObject> myDelegate para que pueda llamar al respondsToSelector:. Pero si lo hace tendrá que declarar todas las variables de esta manera todo el mundo utiliza este protocolo ... Así que esto es mucho más lógico para hacer SomeProtocol adoptar directamente el protocolo NSObject;)

+2

Tenga en cuenta que tener el protocolo original conforme a 'NSObject' no es estrictamente necesario para evitar advertencias. En lugar de usar 'id myDelegate', use' NSObject * myDelegate'. –

+1

Sí, esto también puede ser una solución. Pero inserta entonces una dependencia en los tipos (incluso si es poco probable que ocurra, algunos pueden usar NSProxy o lo que sea, acepto que esto es poco común y raro, pero de todos modos) por lo que viola el principio de obturación de OOP. Si no hay ninguna razón para obligar al usuario a usar una clase que hereda NSObject explícitamente, sino que solo necesita implementar algunos métodos, ¿por qué forzarlo ...?El enfoque correcto es utilizar el protocolo 'NSObject' y el tipo' id ', no el tipo NSObject, para mantener los enlaces débiles entre los tipos y evitar el tipado fuerte. – AliSoftware

2

Herencia ...................

+3

Interfaz Herencia, con mayor precisión. – bbum

+1

Tienes razón, pero iba por la elegancia. –

Cuestiones relacionadas