Protocolos (protocols)

Una de las cuestiones principales en cualquier lenguaje de programación es la menea en la cual se definen los conjuntos de funcionalidades, el cómo tienen que funcionar algo, para que luego alguien pueda realizar una implementación con éxito.

Los protocolos en Objective C son algo similar a los interfaces en Java. Permiten definir un conjunto de propiedades y métodos para que luego puedan ser implementados por parte de otras clases.

Creación de un protocolo

Para crear  un nuevo protocolo se realiza de una manera similar a la de la creación de una clase, utilizando el menús File->New->New File o pulsando Comando+N en Xcode. Nos aparecerá la siguiente pantalla de selección:

Bien estemos creando un programa para iOS o para Mac OSX seleccionaremos Cocoa Touch o Cocoa y en la parte derecha seleccionaremos Objective C protocol y pulsamos en Next. Nos aparecerá la siguiente pantalla:

Aquí podremos configurar el nombre del protocolo, recuerda seguir la misma nomenclatura que con las clases, CamelCase con prefijo. Pondremos por ejemplo MiProtocolo y pulsamos en Next.

Ahora veremos la pantalla de selección de guardado:

Indicamos donde queremos guardar el fichero y pulsamos el botón Create. Y nos debería aparecerá el siguiente código:

//
//  MiProtocolo.h
//  01_clases
//
//  Created by pepesan on 12/03/14.
//  Copyright (c) 2014 pepesan. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol MiProtocolo <NSObject>

@end

Como podemos ver en el código, a parte de los comentarios y el import de las clases fundacionales, nos encontramos con que el código del protocolo se verá incluido entre el @protocol y el @end . A continuación escribimos el nombre del protocolo y luego decimos que debería implementar este protocolo. En este caso sería una especie de herencia de propiedades y atributos de otro protocolo el NSObject por eso se coloca después del nombre del protocolo y entre <>. Como puede verse en el código de Objective C antes de definir una clase NSObject se define un protocolo de como debe funcionar un NSObject.

Con el código de ejemplo decimos que todo protocolo debe funcionar como un NSObject de base y luego contendrá todo aquello que queramos añadir.

Para poder añadir propiedades y métodos lo podemos hacer exactamente igual a como lo hacíamos en una clase, lo único es que no tenemos porque definir la implementación, sino solo las definiciones, por lo que para definir un protocolo sólo necesitamos crear un fichero .h de cabecera.

Inclusión de propiedades y métodos

A continuación  un ejemplo de inclusión de una propiedad y un método:

#import <Foundation/Foundation.h>
@protocol MiProtocolo <NSObject>
@property int i;
– (void) hazAlgo;

@end

Implementación de un Protocolo

Un protocolo por si mismo no tiene sentido si no realizamos implementaciones de dicho protocolo y para ello lo realizamos mediante una nueva clase que llamaremos Implementadora. Creamos la clase de la manera habitual, le indicamos que su padre es la clase NSObject, veamoslo en código del fichero de cabecera:
#import <Foundation/Foundation.h>
@interface Implementadora : NSObject 
@end

A continuación debemos incluir la dependencia del protocolo MiProtocolo, empezamos por añadir el import del protocolo:

#import “MiProtocolo.h”

Y a continuación después del nombre de la clase padre, indicamos entre <> el nombre del protocolo que queremos implementar en la clase:

@interface Implementadora : NSObject <MiProtocolo

De esta manera sería como hacerlo similar al implements NombreDeInterfaz en Java.

Ahora es cuando tendríamos que codificar la implementación del protocolo en la clase, dentro del fichero .m:

#import “Implementadora.h”
@implementation Implementadora
@synthesize i;
– (void) hazAlgo{
    NSLog(@”estoy haciendo algo!”);
}

@end

Como podemos ver sintetizamos la propiedad i definida en el protocolo y realizamos la implementación del método definido en el protocolo.

Así que se puede decir que la clase Implentadora implementa el protocolo MiProtocolo con todos sus propiedades y métodos.

Si necesitara implementar varios protocolos en una misma clase sólo tendría que separarlos con comas dentro de los <>, por ejemplo:

@interface Implementadora : NSObject <MiProtocolo, MiOtroProtocolo

Métodos opcionales y requeridos

Una de las características específicas de los protocolos es que nos permiten indicar que métodos son los requeridos mínimos de la implementación y cuales de ellos son opcionales. Por lo que en el caso de que debamos realizar una implementación de un protocolo siempre deberemos implementar los requeridos dejando a nuestro criterio ver si realmente necesitamos o no implementar los métodos opcionales. 
Veamos un ejemplo de protocolo con métodos requeridos y opcionales:
#import <Foundation/Foundation.h>
@protocol MiProtocolo <NSObject>
@property int i;
@required;
– (void) hazAlgo;
@optional;
-(void) hazOtraCosa;
@end

Como podemos ver disponemos de dos nuevas a notaciones  @required y @optional de esta manera colocándolas delante de cada método podemos indicar si es requerido u opcional respectivamente.

Si dejamos el código de la función implementadora tal como está no debería haber ningún problema, porque hemos implementado el método requerido, y aunque no hemos implementado el segundo método, como está definido como opcional, no tenemos la obligación de implementarlo y nuestro programa compilará sin problemas.

Aunque la comprobación de los métodos opcionales en Objective C se realiza en tiempo de ejecución, el programa fallará si se intenta ejecutar un método opcional no implementado.

Delegados (delegate)

Uno de los usos principales de los protocolos es la implementación de delegados. Los delegados en Cocoa y Cocoa Touch (MacOSX e iOS respectivamente), las bibliotecas gráficas, son los responsables de definir cómo tienen que funcionar las vistas de una aplicación. Por ejemplo el UITableView de iOS suele requerir de la implementación no de uno, sino de dos protocolos, como son el UITableViewDelegate y el UITableViewDataSource .
De esta manera cualquier escena definida en un proyecto iOS requerirá que se implementen un conjunto de métodos en la clase UIViewController que controle una escena.  Las UIViewController son lo más parecido a las Activity de Android. 
Por lo tanto podremos decir que la clase que implemente los protocolos sería una candidata a ser delegada de dichos métodos. Vamos que podría ser capaz de manejar esas vistas. 

Referencias